

[

  {
  "title": "Free Password Generator for Windows",
  "date":"Sun Oct 04 2026 09:47:36 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1791121657,
  "url":"/posts/2026/free-password-generator-windows/",
  "content":"While I sat around the house waiting for Winter Storm Fern to hit us, I decided to spend some time finishing a simple Windows application I started a while back; a simple Password Generator for Windows.\nMost modern browsers can generate and store site passwords for you, but every so often you need a password to use somewhere else but the browser. There are a bunch of free browser-based password generators available online, but I wanted something simple to use on my desktop PC in Microsoft Windows.\nWhen you start the application, the application's main screen opens and it looks like the following:\n\nSelect the number of characters of the generated password (the password length) then select other options for the generated password. Click the Generate button to generate a new password using the options selected in the form.\nWhen you select the Special Characters option, the generator uses the following characters:  ! @ # $ % ^ &amp; * ( ) ? &gt; &lt; / ~ ` : ; + = - { } [ ] * . ,\nYou can download the software for free from Fumbly Diddle Software.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Eleventy Adding Google Maps with Markers",
  "date":"Fri Sep 18 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1789776000,
  "url":"/posts/2026/eleventy-google-maps-markers/",
  "content":"When I started building out the Breakfast Quest site, one of the features I wanted on the site was a map showing all of the reviewed breakfast locations; this post shows how I did it. You can see the resulting map on the Breakfast Quest site's locations page.\n\nThe first thing I did was look at Google Maps as an option, I wanted to use something free and something that would work in any the browser. Google offers developers a Maps Platform that delivers a variety of options. In my case, I wanted to be able to display markers (one for each restaurant reviewed on the site), so I selected the API-based approach.\nGoogle Maps API Key RequiredTo use this API, you must first create a Google Cloud API key you'll embed in your app. For security purposes, you can limit map API access to a specific source domain; this keeps others from using your API key for their maps (and running up API charges in your Google Cloud account). \nEmbedding the Map on the Page\nEmbedding the map on the site's Locations page was easy, all I had to do was create a &lt;div&gt; on the page with a specific dimensions for the rendered map:\n\nNext, I loaded the Maps JavaScript API:\n\nAnd, finally, I loaded the JavaScript code I wrote to initialize the map and display the markers (described in the following sections):\n\nHere's the complete content from the site's locations page:\n\nInitializing the Map\nInitializing the map is easy; I created a JavaScript file called maps.js and added it to the project's src/assets/js/ folder. In the file, I created created an initMap function that creates a map object and points it to the div with the id of map I already added to the locations page.\n\nI didn't want to use the map's default position and zoom level, so when the code initializes the map, it sets the zoom level I wanted then centered the map on the middle of the United States (recognizing that most locations I review on the site will be in the US).\nHow is the initMap function executed? When I loaded the Maps JavaScript library, I passed a callback parameter that identified the function to call after the library successfully loads: callback=initMap.\nGenerating the Markers File\nThe Google Maps API supports a variety of options for loading markers onto a map. I could have hard-coded a data file in the app or I could have built the marker list using JavaScript code. Since I was working with an Eleventy site and Eleventy is so good with working with data files, I decided to generate the marker list dynamically during the build process.\nTo do this, I started by adding longitude and latitude properties to the frontmatter of my restaurant review posts. This allowed me to keep all restaurant review data together in one place and kept me from having to maintain a separate data file for just the location data. Here's an example:\n\nNow that I had a database of location data (longitude and latitude values), all I had to do was get that data into a format that the Google Maps API could load. One of the available options is the GeoJSON file format.\nThe GeoJSON file defines a collection of Features and each feature defines a geometry type. For my purposes, I use it to define points.  I'm not going to go into the details for how to represent the data, instead here's an example from the site.\n\nTo make this work, what I had to do was generate this file and store it somewhere so the locations page could retrieve it and load it in the map.\nNow, you're probably thinking that the solution is to create an Eleventy Global data file for this, but for a variety of reasons this wasn't possible. The most important one is that if I made a JavaScript global data file, it wouldn't be able to process the posts in the site. Now, I could have brute force scanned the file system for posts, which I'd done for my Eleventy Post Statistics plugin, but I didn't want to do that here.\nInstead, I created an Eleventy plugin that generated the data file (writing it manually to the site's files) under the covers of an empty/hidden collection. By creating a collection, my code has access to the collection API and can access anything in the site during the build process. Once it writes the file, the plugin returns an empty collection which is not used anywhere in the site.\nI'm not going to spend any time showing and describing the plugin code, this post is long enough already. You can study the code yourself here. Just trust me that the plugin, when executed, creates a GeoJSON file like the example shown above in the site's /api/locations.json file (which is not in the repository, but generated every time the site builds).\nLoading the Markers in the Map\nAlright, now that I had the locations.json file, all I had to do was load it into the map at runtime. To do this, I had to make a few changes to the initMap function I showed you earlier.\nThe first thing to do is load the data from the file I just generated; that's pretty easy, here's the code:\n\nThis loads the data from the file and adds markers to the map ",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Prettifying and Minifying an Eleventy Site",
  "date":"Thu Sep 17 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1789689600,
  "url":"/posts/2026/eleventy-prettify-minify/",
  "content":"Years ago, I don't remember where, I found some code I could use to minify the code on this site during deployment in production. Aaah, here it is: Minifying HTML output.\nFast forward a few years, I realized that I didn't like how sloppy the site's code was when viewing source when debugging locally. The generated site code often has a lot of extra spacing and no effort is made to align the code. I realized that if I could minimize for production, I could also prettify the site's source when not in production (when working locally or hosting a dev version of the site) and set about making it happen.\nI started by creating a transforms folder in my Eleventy project then moved the minify code from the article linked above into a file called transform-minify.js.\nNext, I went looking for code I could use to prettify the source. A quick Internet search, or perhaps it was AI, pointed me to the npm prettier package and the following code:\n\nI created a new file in my transforms folder called transform-prettify.js and copied the code there.\nFinally, I modified the project's .eleventy.js file so it checks to see if its running in production or not and loads the right transform (minify or prettify) based on that value.\n\nThis works because I have an environment variable in my Netlify hosting environment called NODE_ENV with a value of Production which forces the minification process. In my local development environments, that environment variable is not set, so prettification happens automatically.\nI really like this solution because its clean and doesn't require me to act in any way to get the experience I want in both environments. Simple is good.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Ignoring Pages in an Algolia Index",
  "date":"Wed Sep 16 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1789603200,
  "url":"/posts/2026/eleventy-ignoring-pages-algolia-index/",
  "content":"When I built this site, I followed the instructions in Ray Camden's Adding Algolia Search to Eleventy and Netlify post to add an Algolia index to my site and allow visitors to use search to locate specific articles. This worked well for this site for many years although, like with Ray's site, not many people use search. I assume this is because its just too easy to let Google point people to posts anywhere.\nAs I built out my new Breakfast Quest site, I realized that I wanted to include more than just the site's posts in the search index, I wanted to include some additional pages as well, but not all of the pages.\nRay's post recommended using an algolia.liquid file to generate a permalinked .json file with the index for the site. The file is called algolia.json and 11ty stores the generated file in the site's root folder. Here's the code for the file.\n\nAs you can see from the first line of liquid code in the file, it generates the Algolia index using just the site's posts:\n\nFor my site, I wanted more than just those pages. One of the things I could do is use the 11ty collections.all to get all pages for the index:\n\nBut then that would get all generated files/pages (like the paginated lists of posts which didn't need to be in the index), so I needed to do something else.\nThe solution I settled on was to set a idxIgnore property in the frontmatter on pages I didn't want included in the index. For example, here's the categories page:\n\nWith that in place and all the skipped pages marked with the property, all I had to do was update indexing algorithm to ignore those pages.\nHere's the updated algolia.liquid file:\n\nI didn't write that file, AI gave it to me and I had to study it to understand exactly what it was doing. The comma thing threw me the most, but I finally figured it out.\nThe use of unless flips the code on its head, I don't know why it was written that way, I assume you could right it the opposite way, but I didn't try since this worked.\nThe code starts with comma blank/empty, so the index doesn't start with, you know, a ,. After that though, and it has to reset the variable in every loop, comma contains a comma, so that separates every index entry.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Eleventy Nav Menu Top Level Highlighting",
  "date":"Wed Sep 09 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1788998400,
  "url":"/posts/2026/eleventy-nav-menu-highlighting/",
  "content":"In my Fumblu Workshop site, the template I used (Relativity from Pixelarity) allows me to highlight the currently selected menu item using a class assignment to the highlighted entry (class=&quot;current&quot;). The site uses submenus, and when I launched the site I didn't spend any time figuring out how to highlight the high level menu when one of its submenus was selected. So, when a high level menu item was selected, everything worked as expected, but when one of the submenus was selected, nothing highlighted. The result of this was an inconsistent menu highlighting.\nI had some time this evening and decided to fix this.\nIn the initial version of this, I used the following code for my page navigation.\n\nIn this example, the code highlights the menu item when entry.url matches page.url by assigning class=&quot;current&quot; to just that menu item. This lame comparison is why only high level selections are highlighted. For submenus, the top level nav entry will never match the page url.\nTo fix this, I added a couple of lines of code and modified the comparison:\n\nFirst, I created assignments for menuSegments and pageSegments which creates arrays containing each path segment for the entry.url and page.url.\n\nWith that in place, my highlighting comparison becomes:\n\nWhich checks to see that the menu item and page segments both start with the same value. Since this check only happens on high level nav menu items (the submenus are built later) the highlighting works as expected.\nPostscript\nYou may wonder why I didn't use menu highlighting in this site, that's because the menu for this site is hard-coded, not generated like the Fumbly Workshop site. Perhaps some day I'll use the Eleventy nav plugin for this site as well.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "The Breakfast Quest",
  "date":"Fri Jul 31 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1785542400,
  "url":"/posts/2026/the-breakfast-quest/",
  "content":"I launched a new site recently and added a reference to it on the sites page. Its called The Breakfast Quest and my wife and I started it to write about the diners and greasy spoon restaurants we visit when we're traveling.\n\nWe basically write reviews of restaurants we visit and include some pictures and background on the restaurant. There's a Locations page that maps out all the locations we've visited. I generated a JSON data file automatically from posts and use it to generate the map, I'll write about that here soon.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
  ]
  },

  {
  "title": "Eleventy Plugin Image Caption Simple",
  "date":"Fri Jul 31 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1785542400,
  "url":"/posts/2026/eleventy-plugin-image-caption-simple/",
  "content":"When I coded the Eleventy Plugin Image Caption plugin, I did it for my specific requirements:\n\nAuto numbered image captions (Figure 1: A boy with a dog)\nAutomated reference to images on the page (see Figure 1)\n\nI did it because I like those capabilities in Microsoft Word and I wanted them available to me in an Eleventy site.  By the way, I wrote about that plugin in Eleventy Auto-numbering Image Captions.\nImmediately after I published it, I started thinking about how other site owners would use it and I realized that the plugin wasn't...simple enough for use cases where the site didn't need to reference image captions by reference.\nI set about updating the plugin, adding an imageCaptionSimple shortcode to it that simply added a caption, but didn't store a reference so the imageReference shortcode could refer to it later. I quickly realized though that that approach was just complicating things more since the captions wouldn't work if you intermingled them (used both imageCaption and imageCaptionSimple on the same page).\nSo, I abandoned those changes and created a new plugin called Eleventy Plugin Image Caption Simple (npm).\nThis plugin takes a much simpler approach, it creates a single shortcode called imageCaptionSimple that just takes a single parameter, the caption to add to the page:\n\nFor example, something like this:\n\nIt creates a paragraph with the following text:\n\nI hope this plugin is a little more useful to a wider audience.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Eleventy Auto-numbering Image Captions",
  "date":"Thu Jul 23 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1784851200,
  "url":"/posts/2026/eleventy-plugin-image-caption/",
  "content":"One of the things I like about Microsoft Word is the ability to caption images with an auto-numbered label. Once you do that, its easy to insert a reference to the image file elsewhere in the document.\nWhile working in a new Eleventy (11ty) site, I realized that I missed that capability and set about implementing it. The result of this work is the Eleventy Image Caption plugin that I published today. I built a sample site that demonstrates the plugin's capabilities and included it in the plugin repository and available here (on Netlify).\nThe plugin allows you to do two things:\n\nAdd a auto-numbering label and caption to an image.\nAdd a reference to one of the captioned images elsewhere in a page.\n\nThe plugin is configurable, so you can easily:\n\nSet the label text used in the caption\nBold (strong) or not bold the label\nSet the CSS class assigned to the caption paragraph.\n\nLet me show you some examples...\nBelow is a picture from a recent vacation, to caption it with a label and image number, all I have to do is add a liquid tag immediately following the picture:\n\nThe plugin adds a paragraph tag with a label, number, and provided caption.\n\nImage 1: Vacationing Feet\nSay for example that I want to refer to an image later in the document. To do that, add a different shortcode:\n\nThis shortcode returns the label and image number for the specified image file. Here's an example:\n\nYes, the feet you see in Image 1 are mine.\n\nThe plugin has a couple of small limitations, but it works really well within those limitations. For me, this plugin is most useful for tutorials, especially long ones, where you may want to refer to an image later on a page and not need to describe it to the reader, just use an image caption and reference and you're all set.\nPostscript\nAfter I published the plugin, I realized that I made a mistake in the original implementation requiring the image file path as the index, you can use anything for that parameter, as long as its unique per image caption. I published an update that fixes the docs (readme.md) to reflect that.\nI also realized that not everybody will want to reference the image from elsewhere in the document. For that reason I'll publish a 'simple' plugin that only captions and takes a simpler set of parameters in the shortcode. Stay tuned for that one.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Ridiculous Delivery Status Notification",
  "date":"Thu Jun 11 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1781222400,
  "url":"/posts/2026/ridiculous-delivery-status-notification/",
  "content":"I received the most ridiculous email today, an idiot demanding $1,490 to keep them from releasing who knows what about my internet usage. Yeah, whatever. The fact that they're still sending emails out like this means that some people actually fall for this ridiculousness; I'm sharing so you'll know its just a scam.\nCompletely BogusJust in case you're not sure, this email is completely bogus and you shouldn't do anything they demand you do.\nHere's the email:\n\nWhy is the email bogus? For a lot of reasons, but I'll hit some of the highlights.\nWhile it is possible someone installed a virus on your computer and it is possible that the installed malware is monitoring your activity. It's just not likely. If they are doing it, they're doing it to get a much bigger payout and they're likely not targeting you. They're not doing it to get you to send them money, they're doing it to capture your banking and credit card credentials.\nAll they have do to get you to send money is buy a stolen or captured email address list then send you the email shown above. They believe it will scare you enough to get you to send them money even though they didn't install anything on your system(s) and they don't have anything stolen from your systems. Don't believe them.\nSystems? Most people only use mobile devices right now and the everyday hacker can't do all those things they claim to do on a mobile device. Could they do it on a PC? Sure, but, again, not likely.\nAnyway, I could go on and on pointing out the stupidity of the email, but I'm not going to. If you get one of these, just ignore it and move on.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Read With Jenna",
  "date":"Sat May 16 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1778976000,
  "url":"/posts/2026/scam-read-with-jenna/",
  "content":"I received an email recently suggesting that Jenna Bush Hager was suddenly interested in spotlighting my Learning Progressive Web Apps:\n\nI didn't believe it for a second, mostly because I can't imagine Jenna Bush wanting technical books in her program. I did some research and it seems that my original assessment was correct. Forward thinking? A forward thinking web development book? Innovative content? Yeah, no.\nAnyway, I got a follow-up email:\n\nThis basically repeats the content from the original email. The more we explored the book?\nAnyway, I'm not going to respond; its still clearly a scam. A six year old tech book that nobody bought? Not likely to catch anyone's attention.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Confirmation Needed For Scam",
  "date":"Fri May 15 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1778889600,
  "url":"/posts/2026/scam-confirmation-needed/",
  "content":"I received what I knew to be a scam message yesterday, but I couldn't tell what the scam was. When I opened the email on my Android phone, all I saw was the following a subject line of Confirmation Needed for SLTT71EDUPHA and a message body of:\n\nThere were no links at all in the message.\nStill perplexed, I opened the message on my iPad and noticed that the message contained a .gif file that pretended to be an order confirmation for a large purchase from Geek Squad. Here's the image:\n\nHow did I know this was a scam?\n\nThe &quot;Confirmation Needed for SLTT71EDUPHA&quot; subject line made no sense at all.\nThe &quot;We recorded activity for 40d025a1-79d7-4c76-8c83-a370ba8c3669&quot; was even more useless. If this message was real, the number in the subject line would match the number in the message body.\nThe numbers are just useless, anyone who sees the message text before seeing the image should know this is all nonsense.\nThe message was supposedly from Holasco Tywonda &lt;holascotywonda16@hotmail.com&gt;; hotmail seriously? Not even from Geek Squad.\n\nThe brilliance of the scam message is that it doesn't try to get you to do anything except call the &quot;help desk&quot; to cancel this order. That eliminates all possible link checking and so on. They expect you to freak about the almost $400 order you know you didn't place and expect that in your panic you'll call the number as fast as possible to cancel it.\nUnfortunately, there's no link to make the phone call, so you'd have to copy down the number before switching to the phone app to dial the number. That should be a giveaway as well.\nDon't call the number, its a scam.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Update Amazon Payment Information Scam",
  "date":"Sat Apr 18 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1776556800,
  "url":"/posts/2026/scam-update-amazon-payment/",
  "content":"I received a scam/phishing email yesterday and, when I looked at it on my phone, it looked so real that I thought it was. After studying it for a while, I realized it was fake ignored it until I had a chance to blog about it.  Here's the email:\n\nThe email subject looks real:\n\nAction Required: Update Your Amazon Payment Information lD-2884572407\n\nand that's what made me think it was real. But then when I started actually reading the email content I realized it was junk:\nWe have detected unusual sign-in activity on your Amazon account. For your protection, we have temporarily locked your account.\nTo restore access and secure your account, please verify your identity as soon as possible.\n\nIf you did not attempt to sign in or if this was a mistake, you can safely ignore this email. Your account will remain secure.\n\nSuch a ridiculous morass of content:\n\nThe subject line tells me I need to update my payment information.\nIn the body it tells me they've &quot;locked my account&quot;.\nBut then further on it tells me that I can safely ignore the email.\n\nSo many questions come to mind that confirms that its junk:\n\nHow can I update my payment information if they've locked my account?\nHow can I ignore the email if they've locked my account?\nWhy are they telling me they detected &quot;unusual sign-in activity&quot; in a message that's supposed to be about updating my payment information?\n\nAnyways, it's junk, don't click any links in the email.\nReply-to Email Address\nWhat I couldn't see on my phone but could see on my desktop email client was the reply-to email address on the message:\nAmazon &lt;noreply@lark-international.com&gt;\n\nDefinitely not an Amazon email address. 😄\nCopyright??\nThe other thing that always makes me laugh when I look at phishing emails is that they always seem to put a copyright notice on the bottom of scam emails:\n© 2026 Amazon.com, Inc. or its affiliates. All rights reserved.\n\nAmazon (and most other companies) don't do that. Email content by its very nature isn't copyrighted, I'm stretching a little here, but it generally can't be. Mostly because it's not a published work which is required per copyright law (US anyway).\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Really Stupid Phishing Attempt",
  "date":"Mon Apr 06 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1775520000,
  "url":"/posts/2026/scam-really-stupid-phishing/",
  "content":"Received a really stupid phishing message today. Here's the message content with my personal email domain replaced with mydomain:\n\nAnyway, this is clearly a phishing email; I was just stunned that my personal email domain ended up on their list of companies to phish from (mostly because I'm not a company).\nDefinitely PhishingIf you get a message like this, don't click any of the links in the message.\nThe sent the email to the only email address on the domain and the admin for the domain. So stupid. You'd think they'd try to actually build a database of business domains to use. \nAnyway, the reasons I know this is a phishing attempt:\n\nIts my email domain and there is no security question prompt to change the password. I use my hosting provider's domain management tools for that, there's no other way to do it.\nNo corporate branding. My domain wouldn't have any anyways, but if you work for an actual corporation, you'd expect corporate branding on the email. Without it, this is clearly phishing.\nNo reference to my name. Any email from a corporate help desk would reference you by name.\nHovering over the two links in the email points to the following URL: yinugacize dot z4 dot web dot core dot windows dot net (replacing the . with the word dot). That target site has nothing to do with the domain in question, so couldn't possibly be anything but a phishing attempt.\n\nI don't want the URL showing up in search results or on the page (so you wouldn't accidentally click it), so here it is in all its glory:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "The Fumbly Workshop",
  "date":"Sat Apr 04 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1775347200,
  "url":"/posts/2026/the-fumbly-workshop/",
  "content":"Lately, I spent more time working on woodworking projects than technology projects. I found that I needed to spend more time moving around rather than sitting at my desk typing. Starting back in 2024, I started adding woodworking posts to this site, talking about projects I built or cool jigs I created using my 3D printer.\nAs I approach retirement (I'm not that close yet), I realized I would likely publish a lot more woodworking posts so I decided to create a separate site for my woodworking posts. The site is called The Fumbly Workshop and I launched the site yesterday.\n\nAbout the Name\nYou're probably wondering about the name. Well, one of my favorite Science Fiction writers is Poul Anderson and in a book back in the 1950's he made a reference to fumbly diddling around. Fumbly Diddle quickly became the name of my software company then Fumbly Stuff became the name of my LLC. When it came time to launch this site, I decided to stick with the theme and call it the fumbly workshop.\nWhat's Next?\nRight before I launched the site, I copied over all of the woodworking posts from this site to the new one. I thought I'd delete them from here, but decided to leave them in both places.\nI have a few new posts queued up that I'll write and publish soon. I also plan on focusing on tutorials on the new site as well as product reviews.\nCheck out the site when you get a minute.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Inappropriate GitHub Solicitation",
  "date":"Fri Apr 03 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1775260800,
  "url":"/posts/2026/scam-github-solicitation/",
  "content":"I received a few emails like the following recently:\nFrom: James Ferry &lt;ferry.j@worldtechglobal.site&gt;\nDate: April 2, 2026 at 11:54:58 AM EDT\nTo: john@johnwargo.com\nSubject: Saw your profile – quick intro\nReply-To: topcodebeast53@gmail.com\nHi John M. Wargo,\n\nI came across your GitHub profile (https://github.com/johnwargo) and see you're based in the US.\n\nI'm James, from the Philippines—over 10 years in software development. Salary levels here don't match the \nUS market, so I'm focused on a long-term partnership with someone in the US, not a one-off.\n\nOur collaboration model:\n\n- I apply to US roles using your professional profile (you're the face of the engagement).\n- You attend interviews; I provide full prep and technical backup so you're ready.\n- Once a role is secured, I handle delivery; you stay in the loop and in control.\n- Revenue is shared on a clear, agreed structure—fair and transparent.\n\nThe aim is something that scales: a few solid contracts can become steady income and a real partnership. No scam, \nno risk to you—I'm happy to share references or jump on a short call before we commit.\n\nReply if you're open to exploring a long-term collaboration.\n\nBest regards,\nJames\n\nI originally didn't think it was a scam, mostly because the only option for me is to reply to the email. It just seemed like a very inappropriate 'business' proposition. If this wasn't some sort of scam message, I can't think of any reason why a GitHub user with enough public work to have a reputation would ever, even consider participating in this kind of scam. I certainly wouldn't. If the GitHub user didn't have any sort of reputation, then this approach wouldn't work either. This just doesn't make sense.\nBut, then I started really looking at the message and noticed a couple of things.\nFirst of all, the replyto address  (topcodebeast53@gmail.com) doesn't match the sender's email address (ferry.j@worldtechglobal.site). That seems weird to me, if this person really wanted to do a scam consulting gig through me (not that I ever would), why wouldn't the replyto address not be the same as the sender's? And, if this really was from a business, why would the replyto be a gmail address?\nNext, I checked out the worldtechglobal dot site, well, um site. It doesn't exist. Now, it's possible, but not likely that the domain's used solely for email, but if I worked for a reputable company, why wouldn't there be a web presence associated with the email domain?\nAnyway, I'm not responding to the email and I've blocked the sender address. You should stay away from this on in my opinion.\nPostscript\nI received another email from James today, but it was from a worldtechglobal.website email address except from worldtechglobal.site. Why would anyone fall for this? There's no way I'm tarnishing my reputation by working with this guy, but why send me two messages from different addresses? Because he's a scammer.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Phishing"
  
  ]
  },

  {
  "title": "Eleventy Generate Posts Utility Updates",
  "date":"Thu Mar 19 2026 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1773964800,
  "url":"/posts/2026/eleventy-generate-posts-utility-updates/",
  "content":"I'm building a new site that I plan to launch soon. As part of the development process, I wanted to load the site with a bunch of posts, so I turned to my handy dandy Eleventy Generate Posts to do the job for me. Unfortunately, the API I used in the utility to generate post titles using random words was no longer available.\nI had some work to do. I quickly found a new API to use and was able to fix it with minor changes. I also found a couple of things I wanted to clean up, so I made those changes as well. I use timestamps instead of dates in this site and the one I'm working on, so I also added an option to write the timestamp to generate post's front matter. That became version 0.0.7 of the utility.\nAfter I published the fixe(s), I realized that I really didn't have much (any) error checking in the code to fail gracefully when the APIs don't work (or the fetch command used to retrieve content fails in some other way). I put the fetch calls in a try/catch block and also check for HTTP OK (200) before attempting to process any retrieved data. That became version 0.0.8 of the utility.\nIf you tried using this utility and it failed for you, now its all fixed so please try it again.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Node.js"
  
  ]
  },

  {
  "title": "Randomly Crashing An Arduino",
  "date":"Mon Feb 23 2026 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1771891200,
  "url":"/posts/2026/randomly-crashing-arduino/",
  "content":"I'm helping a friend build a NeoPixel-based throttle gauge for his Autocross race car. He records video of all his runs and wants the gauge to show in the recording. For a variety of reasons, we've been plugging away at this project for months and I've been struggling to complete it. I designed a custom circuit board for the gauge and my friend designed a custom enclosure for it. The most difficult parts of this project is debugging an Arduino-based solution inside a race car in real time.\nAnyway, we spent part of last week refactoring the code in an effort to fix some issues we had accurately displaying the throttle position in LEDs. The throttle generally floats at the low end, when the throttle isn't pressed, the Arduino records a wide variety of values, all of them wrong. So we set about hard coding lower and upper limits for the throttle values (voltage values between 0 and 15) and when we tested it, it seemed to work.\nIt didn't.\nDuring some additional testing, we noticed that often when we let off the throttle, the arduino device reset. After about 8 times throttling to maximum, when we let off, the Arduino randomly rebooted.\nI previously had a divide by zero error in the code, so when this random rebooting started, I studied the code looking for places where I could possibly divide by zero. I didn't find anything, but this was definitely a good place to start.\nNext, I started looking for other places the sketch could crash and, fortunately, I found it.\nMy friend wanted to narrow the range of throttle values that drove the LED gauge. The ESP32 device running the sketch measures analog voltages in a range from 0 to 4096, but for a variety of reasons (that aren't important now) we only cared about values between 450 and 2000 as shown below:\n\nThe project has 15 LEDs in a strip, and my friend wanted to turn all of the LEDs White when the throttle was at 90%. So that led to this code:\n\nThe pixelRatio constant allows the sketch to know how many throttle values are required to illuminate a single LED (NeoPixel).\nLater on in the code, I use the following calculation to determine how many Pixels to illuminate:\n\nThis code can't generate a divide by zero error since pixelRatio can never be zero unless done by purpose. The code can, however, generate a negative pixel count if throttleValue is less than THROTTLE_MIN. This does happen periodically since the throttle value reading can be below THROTTLE_MIN but the sketch essentially ignores analog readings below THROTTLE_MIN.\nLater on in the sketch, I do some stuff to get the gauge to accurately display the LEDs like I want, and this is where the sketch crashes. Take a look:\n\nThe issue is in the two for loops the code uses to illuminate the gauge LEDs using the value in currentPixelCount in the loop bounds.\nFor example, take a look at the code that illuminates the throttle position in Green:\n\nWhen currentPixelCount is less than zero (which I've already proved is possible) then the loop crashes with an array out of bounds error. Assuming, for example, that currentPixelCount is -5, that makes the for loop look like this:\n\nIn this example, the i++ increments i in every loop, but i starts at 0 and the condition for ending the loop is when the value for i is less than 5. For this example, i is never less than 5 and the sketch crashes as soon as i exceeds the upper bounds of the array.\nThe second place the sketch crashes is in the following code:\n\nAssuming the same value for currentPixelCount (-5), the for loop looks like this:\n\nIn this case, the sketch crashes much faster; it crashes in the very first loop iteration as soon as it executes this array assignment:\n\nIt crashes because since i = -5, there is no -5th element in the array (Arduino arrays start at index 0);\nSo, how did I fix the code? Well, I need to accept throttle readings less than THROTTLE_MIN, but not attempt to illuminate any LEDs when less than THROTTLE_MIN. I did this by checking to see if throttleValue was less than THROTTLE_MIN and setting currentPixelCount to zero in this case. Here's the code:\n\nWith this code, currentPixelCount is always an integer value greater or equal to zero which is exactly what the sketch needed to never exceed the tleds array bounds.\nI hope this article saves you some troubleshooting time when working on a sketch that randomly reboots the Arduino device.\nJust in case you're interested, you can find the full code for the sketch in Throttle &amp; Brake Gauge.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Biscuit Joiner Jig",
  "date":"Tue Feb 03 2026 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1770163200,
  "url":"/posts/2026/woodworking-biscuit-joiner-jig/",
  "content":"\nNote: I moved all my woodworking posts to my new woodworking blog at fumblyworkshop.com.\n\nBack in September, I purchased a new table saw for my workshop. I have a really small shop, so for the one I replaced, I created a plywood top for it so I could use the saw for storage when I wasn't using it. I recently decided to do the same thing for the new saw; here's a picture of the result.\n\nThe distance between the table saw top and the rails on either side was about 1/2 inch, I decided to use 3/4 inch 'legs' to hold the top off of the cast iron top. This left 1/4 inch between the saw top and the cover.\nSince the legs for the top were very short, I decided to do an edge on edg binding between the top and the legs as shown in detail in the following image:\n\nI decided to use biscuits to assemble the cover, connecting the legs to the top. Since I was working with such a large piece of plywood (30&quot; x 60&quot;), I knew it would be difficult (although not impossible) to reliably align the bottom of the biscuit cutter with the edge of the top.\nNormally, I'd hold the piece being cut vertically (using stops and clamps) and cut with the joiner flat on the table top. But when working with a piece of wood this large, that wouldn't work. I could clamp a 1&quot; or greater piece of wood along the edge of the top and hold the top alongside that guide while cutting biscuit slots, but I knew that would be cumbersome and unreliable as well.\nI decided instead to design a 3D printed jig I could use for this (and use again later if needed). You can find the jig here: Biscuit Joiner Jig Free.\n\nThe jig has an 1/2 inch overhang that covers part of the wood being cut. It also has clamping pads you can use to hold the jig in place while cutting. When you mount it to your piece, align the guide in the jig with the cut line on the wood as shown in the following figures.\n\n\nNext, you place the biscuit cutter within the jig then align the cut mark on the biscuit joined with the cut line on the wood then slide the biscuit joined into the face of the jig.\n\nIf you want, not shown here, you can mark the cut line on the bottom of the biscuit joiner so its visible when the biscuit joined is fully inserted in the jig.\n\nWith this in place, I have a solid and reliable way to cut biscuit slots in the face of a large piece of plywood.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Designing a Vertical Slat Positioning Jigs",
  "date":"Mon Feb 02 2026 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1770076800,
  "url":"/posts/2026/woodworking-slat-positioning-jig/",
  "content":"\nNote: I moved all my woodworking posts to my new woodworking blog at fumblyworkshop.com.\n\nI recently build a love seat/bench for my driveway using plans I purchased from Rockler. I made the bench out of Cypress wood so I wouldn't have to finish it, it would age naturally in the elements. Here's the bench:\n\nIn Spacing Slats Evenly I described some simple spacers I designed to help me align the seat slats evenly. When it came to assembling the bench back, I needed something else to hold the slats in place vertically as I screwed them into the side rails. I decided to create a special set of jigs I could use to do this, here they are:\n\nThe jigs allowed me to hold the vertical slat (that little short slot on the outside of the jigs), then clamp them in place against the bench. This freed up my hands to screw the slats in place.\nI call the design Slat Positioning Jigs and the following image shows them in Tinker CAD.\n\nAs you can see in the following figure, the jigs (one for each side of the bench) hold the slat in place; I used a spacer to set the distance between the slate. I set the slat in the slot on the jig, then clamped it in place; setting the distance from the front of the side rails (as showm om the figure).\n\nThis image shows the bench from the back, see how the clamps use the flat section of the jig as a clamping surface.\n\nWith this in place on both sides of the bench, I had two hands free to screw the pocket hole screws in the holes shown in the figure.\nThese jigs saved me from struggling with clamps to shimmy the slats in place. I knew there was no way I could do that and hold them solidly in place as I screwed in the pocket screws in place. It also saved me from asking my wife to try to hold one side in place as I worked on the other. This work saved me a lot of time and effort during assembly.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Added Eleventy-Fetch to the Site",
  "date":"Mon Jan 12 2026 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1768262400,
  "url":"/posts/2026/eleventy-added-eleventy-fetch/",
  "content":"A while back, I found an article from Raymond Camden demonstrating how the Eleventy Fetch plugin works.\nSeveral sections of this site make API calls to get the content (Github Repositories, npm packages, and Popular Posts) and I know that when I'm testing something new on the site, repeated requests could get me rate limited. I decided I wanted to use the eleventy-fetch plugin to cache those requests and finally got around to implement it yesterday.\nYou won't notice the difference, but I do. Anyway, I made the change and it was really simple.\nFor example, the site generates the npm packages list using a simple REST API; the code to do this is in the site's `_data/packageList.js file. Before implementing the eleventy-fetch plugin, the code looked like this:\n\nWith it, it looks like this:\n\nThe new code replaces the call to the JavaScript fetch method with a call to the plugin's Fetch method (a simple change in capitalization in the method name).\nNext, I had to add a new object to the request that tells Fetch how to work:\n\nThe duration property tells the plugin how long to cache the data.\nThe type property tells the plugin how to pre-process the data returned by the Fetch operation. In this case, since I'm telling it the request returns JSON data, the plugin automatically executes the data = await response.json(); from the original version for me. I no longer have to worry about converting my data, the plugin takes care of it for me.\nWhen the Fetch operation completes, data contains the JSON array returned by the API.\nThe plugin supports a [returnType](https://www.11ty.dev/docs/plugins/fetch/#return-type){target=&quot;_blank&quot;} type` that returns the standard HTTP response object so you can continue to do all your normal processing if you want. I find that letting the plugin handle the JSON data processing is just simpler.\nIf your remote procedure call requires special headers or additional options, you can add them to the request through the addition of a fetchOptions type in the Fetch request.\nHere's an example from the eleventy-plugin-github-repos plugin:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Eleventy Require Not Defined in ES Module Scope",
  "date":"Sat Jan 10 2026 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1768089600,
  "url":"/posts/2026/require-not-defined-in-es-module-scope/",
  "content":"As I described in Eleventy Adding Page Links to a Post, I published a new Eleventy plugin yesterday that delivers a shortCode that generates a list of links from the current page. When I built the plugin, I built it using Eleventy 3.12.\nAfter publishing the plugin, I tried to implement it on this site but the site crashed and burned (wouldn't build). I suddenly remembered that I never completed this site's upgrade to Eleventy 3.x. I upgraded all of my other sites, but for this one I kept running into module problems, so I reverted it to Eleventy 2.x.\nWell, I had this shiny new plugin I wanted to put to work, so I had to figure this out. I went through all of the steps and still bumped up against module problems.\nHere's what I did:\n\nAdded type: module to my package.json file.\nChanged all my requires to imports\nChanged all my plugins to export default function() {}\nUpgraded all my packages to the latest versions (I did this late in the process after I couldn't get this to work any other way), just in case.\n\nEvery time I tried to build the site, I received a variant of the following error:\n[11ty] Eleventy Fatal Error (CLI):\n[11ty] 1. Error in your Eleventy config file 'eleventy.config.js'. (via EleventyConfigError)\n[11ty] 2. There was a problem importing 'eleventy.config.js' via import(esm) (via EleventyImportError)\n[11ty] 3. require is not defined in ES module scope, you can use import instead\n[11ty] This file is being treated as an ES module because it has a '.js' file extension and 'D:\\dev\\11ty\\johnwargo\\package.json' contains &quot;type&quot;: &quot;module&quot;. To treat it as a CommonJS script, rename it to use the '.cjs' file extension. (via ReferenceError)\n\nI've tried changing the Eleventy config to eleventy.config.cjs as suggested, but then I get a different error (I didn't save it). Changing it to a .mjs extension doesn't make it any better.\nHaving spent one or more hours on this, I decided it was time to ask the experts over on the 11ty Discord. Member uncenter quickly pointed out that I was probably still using require somewhere in the site (I didn't think I was, but I was wrong). Member vrutehagel even went ahead and found all the instances I'd missed and fixed them in a pull request; simply amazing.\nReplacing require with importBe thorough when upgrading an Eleventy site to version 3, you must fix all of your code's use of require. Not only must you change how you load modules included with your project, you must also replace each module's use of require as well - as shown in the image below.\nWhat I'd done, likely multiple times as I tried to make this work, was fix the modules/plugins I'd written (or borrowed from other sites), but I missed fixing any of my code-based Global Data Files and I definitely missed fixing require statements used within the site's modules.\nThat was a huge miss for me and cost me a lot of time.\nHere are some examples from the PR:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Eleventy Adding Page Links to a Post",
  "date":"Fri Jan 09 2026 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1768003200,
  "url":"/posts/2026/eleventy-adding-page-links-to-a-post/",
  "content":"I often put a lot of links in my longer posts and a few months ago I started thinking about adding a list of links to the top of my posts on this site. I had some extra time this week, so I created a plugin to do that for me. This post introduces the plugin.\nThe plugin's called Eleventy Plugin Markdown Post Links and you can find the source code on GitHub and the installable package on npm\nAbout the Plugin\nThe plugin adds an 11ty shortcode called pageLinks to the site you can use to add a list of the page's links to the page.\nAdd the shortcode to a page's template to have the links appear on every page, or place the shortcode at the top or bottom of a long article to generate links for just that page. The plugin also supports a configuration option, minimumLinks, that instructs the shortcode to generate links only if there are a specific number of links on the page.\nThe plugin supports the following options:\nList Types:\n\nSimple list - Generates a simple list of page links with each as a separate paragraph in the page.\nOrdered list - Generates a list of page links as an ordered list using the &lt;ol&gt; and &lt;/ol&gt; tags\nUnordered list - Generates a list of page links as an ordered list using the &lt;ul&gt; and &lt;/ul&gt; tags\n\nList Options:\n\nCollapsible list - Link list and renders it in a collapsed section on the page using the &lt;details&gt; and &lt;summary&gt; tags.\nNew Tab - Links open in a new tab using target=&quot;_blank&quot;.\nStyled List - Allows you to apply a CSS class to the list container on the page.\nMinimum Links - Only generate the link list when there's at least a specified number of links on the page.\n\nImplementation on this Site\nMy favorite features of the plugin are the minimumLinks setting (which allows me to only generate the link list when there's more than the specified minimum links on the page) and the Collapsible link type which uses a very small amount of space on the page; click the list title to expand the links on the page. You can see an example of this in action at the top of this page.\nHere's how I've implemented the plugin on this site:\n\nSample Application\nRather than duplicating the docs here, you can learn more about the plugin in the project's readme file. I also built a Demonstration Eleventy site that demonstrates all of the options available in the plugin.\n\nFuture Plans\nRight now, the plugin uses positional parameters in the shortcode; I want to get away from that and use named parameters. Expect an update soon.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Robinhood Withdrawal Attempt Detected",
  "date":"Sun Jan 04 2026 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1767571200,
  "url":"/posts/2026/scam-robinhood-withdrawal-attempt/",
  "content":"Received a simple phishing email today; this one's interesting because the scammers sending this email avoided many sophisticated ways to make this email look legitimate and simply pushed me to call a number where they'll supposedly help me resolve the issue.\nHere's the email:\n\nThe message starts with:\n\nVerification Needed to Process Robinhood Withdrawal: SecID: XX5VW\n\nWhich would immediately get your attention if you happened to have a Robinhood account, I don't.\nThe message provides some information about the detected withdrawal attempt then asked me to call a number to &quot;take action&quot;. The message contains no links except one to make it easy for the recipient to tap to call the company to ask them to block the withdrawal.\nThe phone number listed is a Texas phone number, but they included the &quot;+1&quot; in the number which means they're targeting a user outside of the US (US customers wouldn't use a +1 prefix when dialing).\nNotice too that they formatted the number like an international number with the last four digits split up into two parts.\n\n+1 (210) 547-18-26\n\nYeah, this definitely isn't a valid email, Robinhood would never send a message like this.\nAnother issue is, of course, the sender email. Its noreply at mma.com.br which is a wireless provider in Brasil.\nDon't click on the link if you get this email.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Goodreads Reading Challenge 2025",
  "date":"Sun Dec 28 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1766966400,
  "url":"/posts/2025/goodreads-reading-challenge-2025/",
  "content":"I checked out my Goodreads Reading Challenge statistics for 2025 and I did quite well against my goal this year. I've been working through all of my old books I've had lying around and trying to minimize new book purchases (with little success). If I read in 2026 like I did in 2025 (and previous years), I should be able to get through most of them next year.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Phishing Marriott Pillow Promotion",
  "date":"Tue Dec 23 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1766534400,
  "url":"/posts/2025/phishing-marriott-pillows/",
  "content":"I received a lot of new spam and phishing messages lately; I have some analysis articles queued up to write. For this post, I'm writing about a very professional looking phishing email that appears to be from Marriott. I'll prove here that the message is not from Marriott and they're not giving customers free pillows.\nHere's the email I received:\n\nNotice how its very professional looking, that's what first caught my eye when I received it. The writing is excellent and there's only one misspelled word that I noticed.\nTo help the search engines, here's the main body from the message:\n\nConfirmed Phishing EmailThis is clearly a spam or phishing email. Marriott is not giving 800 customers a free two night stay and pillows.\nThis is clearly a spam or phishing email. Marriott is not giving 800 customers a free two night stay and pillows. There are few glaring issues with this email, but it is very clear that it's fake.\nFirst of all, the only place the email spells Marriott correctly is in the subject line:\n\nYour thank you gift from your Marriott stay\n\nIn the body of the email its spelled 'Marriot'. Its possible that Marriott would send an email with that mistake, but it's not likely. You'll notice too that there's no Marriott logo anywhere on the message; Marriott usually includes a logo and/or a banner image in promotional emails.\nThose are really the only ways I could tell at first glance that the email was fake.\nLooking deeper at the email, I noticed a block of text at the bottom of the email in a very small text size and greyed out so it's hard to see. Here's the content I found there:\n\nHe leaned back in the chair, the leather creaking softly. &quot;So, the entire concept hinges on that initial moment of recognition,&quot; he said, gesturing with his pen. &quot;Not a transaction, but an acknowledgment.&quot; Across the table, she nodded, tapping her notebook. &quot;Exactly. It's the difference between handing someone a manual and showing them the first step. The rest follows naturally if the foundation is solid.&quot; Outside the conference room window, the city moved in its usual patterns, cars flowing like rivers of light in the gathering dusk. They had been at this for hours, mapping out sequences and user pathways. &quot;Remember the feedback from the pilot group&quot; she asked. &quot;The common thread was appreciation for clarity, for not having to decipher intent.&quot; He made a note. &quot;Clarity. Simplicity. Directness. They're not just buzzwords here; they're the operating system.&quot; A quiet settled between them, the productive kind filled with turning gears. She thought about how complex systems often boiled down to elegant, simple principles. The coffee in the carafe had gone cold, but neither moved to get more. &quot;We should break,&quot; he said finally, stretching his arms. &quot;Let it settle overnight.&quot; &quot;Agreed,&quot; she said, closing her laptop. The ideas would percolate, find their own connections in the background. As they gathered their things, the cleaning staff's vacuum hummed from a distant hallway, a familiar end-of-day sound. Walking to the elevator, they discussed mundane things: weekend plans, a new restaurant opening, the relentless march of garden weeds. The work was important, but so was this, the easy shift from collaboration to casual conversation. The elevator doors slid open with a soft chime, offering a bright, mirrored interior. They stepped in, the day's diagrams and discussions folding away for the evening, leaving room for thoughts of home, of dinner, of quiet hours ahead.\n\nIn the very early days of spam messages, scammers hid paragraphs of text in the message to trick malware scanners into believing it was an actual email between two people. So many years later, I'm not sure why this is there as I thought scammers and scanners moved on from that.\nWhen you look at the link behind the Participate to Get Your Pillows + 2 Night Stay button on the email, you can definitely see that this email is a problem. The link points to the following URL:\n\nNote: I'm showing this as an image so people don't accidentally click on it and I don't want to get blocked by search engines.\nWhen you click on a link, a browser window opens and redirects to the following link (with a bunch of data omitted):\n\nIt opens a page that looks very much like a Marriott page asking you to fill out a survey in order to earn your prize. Its not a Marriott page, look at the URL in the previous image. I didn't try this, but I assume that when you click the Start Survey button you'll be prompted to provide your Marriott credential and that's where they get you.\n\nNotice the sense of urgency they create at the bottom of the page: Offer expires in 4 minutes. When they do this, they're trying to get you to ignore any issues with the page and start the survey as quickly as possible.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Firebase Hosting a HTML Boilerplate Site",
  "date":"Wed Nov 19 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1763596800,
  "url":"/posts/2025/firebase-hosting-html-boilerplate/",
  "content":"Last night, I started playing around with a new Firebase project; deploying a hosted web app with some functions. I decided to use the HTML Boilerplate template for the web app and want to run a build before deploying the web app to Firebase. Looking around at the documentation, I struggled to find an easy way to do this.\nHosting Project Configuration\nI started by placing my HTML project in a folder within the Firebase project, lets call the folder... static. With the standard settings (including functions), my project folder looks like the following:\n\nWithin the static folder, I have a dist folder where the HTML Boilerplate project build process puts the generated site files. To configure Firebase hosting to deploy the site using the files in the dist folder, all I had to do was make a small change to the project's firebase.json file:\nThe file has a hosting section with a public property that points to the site's deployable files.\n\nTo configure this for my project, all I had to do was change the public property to point to the static/dist folder instead of the static folder I selected when I initialized the project.\n\nHere's the completed configuration file:\n\nWith that in place, the project deploys successfully to Firebase Hosting.\nAutomating Site Builds\nFor this to work, I had to manually build the project every time I deployed the site. That isn't fun and I knew I could automate it somehow.\nFirebase allows you to add a pre-deploy step to your deployment process, simply add a predeploy property to the firebase.json file's hosting section as shown below:\n\nBut, with that in place, it doesn't work since the project's package.json file that contains the build command definition is in the static folder, not the project's root.\nHacking away at this, I decided to make a little batch file that did the work for me:\n\nBut that approach required that I manually execute the batch file every time I wanted to deploy the project. This isn't a good solution.\nThe only solution I could come up with was to copy the web application project to the project root. With that in place, the web application project's package.json file was where it needed to be and the predeploy option worked as expected.\nHere's the modified hosting settings for my project:\n\nand here's the complete firebase.json file for the project:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Cloud Development",
  
    "Web Development"
  
  ]
  },

  {
  "title": "UPS Tracking URL Builder",
  "date":"Thu Sep 25 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1758844800,
  "url":"/posts/2025/ups-tracking-url-builder/",
  "content":"When you order packages online, a lot of vendors provide you with a tracking number instead of a tracking URL for your package. Or, when you get a tracking URL from UPS, the URL has a bunch of extra junk in it that isn't needed to actually track the package. In frustration, I built a little Windows app (in Delphi, of course) that takes a UPS tracking number and converts it into a tracking URL you can use to, you know, track the package.\n\nYou can find the app's source code at UPS-Tracking-URL-Builder-Delphi and download a Windows installer from Releases.\nA tracking link shared by UPS looks something like this:\n\nIt includes internal tracking stuff UPS uses to track your use of the URL (I guess). If you paste the actual tracking number into the UPS site, the site opens a tracking page using a URL in the following format:\n\nMy little application takes a UPS tracking number (in the US they begin with a 1Z) and converts it to the URL format shown above.\nIn the app, you simply click the Copy button to copy the generated URL to the system's clipboard or click the Open Tracking URL to open the generated URL in the browser.\nThe Auto close checkbox, when enabled, automatically closes the application after you click either the Copy or Open Tracking URL buttons.\nWhy do I want the tracking URL in short format?\nYou may have asked yourself why I want the tracking URL in short format. I use todoist to track all of my incoming packages and I store the tracking URL in the comments field so I can click the link to check the current delivery timeframe.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Delphi"
  
  ]
  },

  {
  "title": "Learning Progressive Web Apps Site Shutdown",
  "date":"Sat Sep 06 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1757203200,
  "url":"/posts/2025/learning-progressive-web-apps-site-shutdown/",
  "content":"Back in the middle of 2019, I published my last book: Learning Progressive Web Apps. It was probably my most mainstream book, a book about web development rather than my highly focused books on mobile development for PhoneGap and BlackBerry. I was really proud of that book, it was just the right length and the publisher printed it in color which made the content more interesting.\nAfter a little more than 6 years on the market, I decided to let the learningpwa.com domain registration expire and dismantle the site. The site gets very little traffic and it been a long time since I heard from a reader. You can still find the book's source code at learning-pwa-code and can ask questions in the repo.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Mobile Development",
  
    "Web Development"
  
  ]
  },

  {
  "title": "Spacing Slats Evenly",
  "date":"Tue Jul 15 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1752624000,
  "url":"/posts/2025/woodworking-spacing-slats-evenly/",
  "content":"\nNote: I moved all my woodworking posts to my new woodworking blog at fumblyworkshop.com.\n\nWhen I built the love seat I described in my previous post, one of the assembly tasks for the seat was to screw slats to the frame spaces a quarter inch apart. Since each slat was 46 inches wide, I had to come up with a unique approach to doing this consistently with only a single pair of hands.\nThe simplest solution would be to just cut a piece of 1/4 plywood 46 inches wide and insert it in place. Unfortunately, any pieces of 1/4 inch plywood I had that long wasn't straight enough to do the job and I'd need another set of hands or a clamp to hold it flat between the slats.\nI tried cutting smaller pieces of plywood, but they kept falling through the slats.\nRemembering that I had a high end 3D printer upstairs in my office, I quickly came up with a solution. I crafted a set of T-shaped shims that solved my problem in a variety of ways.\n\nI made all of the sides 1/4 inches in width so I could insert them in any orientation and they'd still do the job. I made the top of the T an inch and a half wide so it would sit comfortably on top of the slats. I printed 4 of them so I could use them on both ends and on both sides of a slat. What you see in the image below is the spacers placed on the already assembled love seat, I forgot to take a picture during assembly.\n\nI created the spacers using Tinkercad, it's a very simple design, you can find the design at Quarter Inch Spacer 2 ways.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Drilling Holes Consistently Across Multiple Pieces",
  "date":"Sat Jul 12 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1752364800,
  "url":"/posts/2025/woodworking-drilling-holes-consistently/",
  "content":"\nNote: I moved all my woodworking posts to my new woodworking blog at fumblyworkshop.com.\n\nLast week, I competed construction of the Rockler Rockler Modern Patio Love Seat Plan with Templates project. We have a couple of iron chairs next to our garage that we use all the time, and I was looking to replace them with something more comfortable and much better looking. Here's the completed project; I used Cypress wood for my version of it:\n\nOne of the features of the seat is a row of 8 slats lined up as the base. The plans called for countersinking screws holding the slats onto supports hidden underneath and I wanted to ensure I did a good job on this since the screws are visible from the top of the seat; I wanted them all to align beautifully!\nHere's a close-up of the resulting holes I wanted to make (and eventually did). All lined up and beautiful.\n\nThe easiest way to do this is to grab a cordless drill or use a drill press to drill the countersink holes. With this approach, you can try to align your holes across multiple boards (both ends, of course), but your chances of doing that successfully are really small.\nAnother option is to pull out a ruler and pencil and mark up the ends of each board with the exact location of each countersink hole. Experience told me this would be a slightly better approach, but still not the best because it's not always easy to consistently put the countersink bit down on the mark every time (in this case 16 times - 8 boards with a hole on each end of the board).\nLeaving Nothing to ChanceOne of the things I learned a long time ago about woodworking is that successful woodworkers spend a lot of their time planning and setting up their actions (drill, cut, stain, whatever) so they can't make mistakes. They leave nothing to chance. The jig I explain a little later is an example of this approach.\nI realized that there was no way for me to accurately drill 16 countersink holes in these 8 slats by hand without making a bunch of mistakes. I decided to use my 3D printer to create a jig that would hold each slat in place on my drill press so I could drill the countersink in the exact same place on each end of each board.\nSo I fired up Tinkercad and built a simple block with an opening that was exactly as wide and tall as the slat with some extra space around it for strength. Here's what it looks like in Tinkercad:\n\nI knew I'd use my drill press instead of a handheld drill and the table for my drill press was cast iron, so I added holes to mount some rare earth magnets to the jig to hold it in place on the drill press. I ended up not having any magnets lying around to use for this purpose, so I ended up using two-sided woodworker's tape to hold the jig to the drill press while I drilled the holes.\nHere's an image of the jig in action.\n\nI didn't use a true countersink bit for this project. For mounting the slats, I used pan head screws, so I used a 3/8&quot; forstner bit to drill the countersink - the forstner bit gives the countersink a flat bottom. Next, I used a traditional bit to drill a pilot hole through the remainder of the slat thickness.\nYou can find my Tinkercad project at Countersink Guide for Drill Press 2 Inch; I hope you find this helpful.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Setting Windows File and Directory Timestamps to Now",
  "date":"Sat Jun 28 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1751155200,
  "url":"/posts/2025/windows-file-timestamp-now/",
  "content":"When working on a book and sometimes while writing software applications, I like to set my project files (Word documents or other files) to the same timestamp. I'm not sure why I started doing this, but it allows me to set a sort of release grouping on the files based on timestamp.\nFor years I used a free Windows application called Attribute Changer for this. I don't remember how I found it, but it became a staple on my development systems over the years and I really relied upon it. The Windows Shell Extension allows you to change file attributes (like hidden or read-only) as well as the timestamps for Created, Modified, and Accessed. The application's grown over the years and added a bunch of very flexible configuration options, but as it did that, it became more complicated to use. In its current version, I can't simply invoke the shell extension like I always have and have it automatically do what I want. Its not that much harder to use than before,  but it does more than I need it to do now and, like I said, the user experience is...cumbersome.\nI always wanted to learn how to code a Windows shell extension, so I set about implementing my own version of the utility I needed. I started building something that handled file attributes along with file and directory timestamps, but then I realized that all I was doing was building a clone of Attribute Changer.\nI finally settled on building a shell extension that simply changed one or more file and/or directory timestamps to the current date/time (timestamp). I call the application Timestamp Now.\nFree DownloadDownload Timestamp Now from Fumbly Diddle Software\nThe application's interface is very simple and its easy to use. In Windows File Explorer, simply select a set of files and/or directories, then right-click on one of the selected files and select Timestamp Now. The shell extension loads and displays the following interface.\n\nFrom here, you can select which timestamps you want modified:\n\nCreated\nModified\nAccessed\n\nNext, you select the format for the timestamp:\n\n\n\nOption\nDescription\n\n\n\n\n##:##:##:##\nUse the full time value as the timestamp.\n\n\n##:##:##:00\nUse the current time with milliseconds zeroed out.\n\n\n##:##:00:00\nUse the current time with seconds and milliseconds zeroed out.\n\n\n\nThe options allow you to leave the timestamp alone (using the current date/time) or zero out the minor parts to make the changes look cleaner. When changing the timestamp for files, I generally zero out the seconds and milliseconds so the timestamp looks artificial, notifying me that I changed the timestamp.\nThe application's a free download from Fumbly Diddle Software. I hope this little utility helps you.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows",
  
    "Delphi"
  
  ]
  },

  {
  "title": "Magnetic Dust Collection Port",
  "date":"Fri Jun 27 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1751068800,
  "url":"/posts/2025/woodworking-magnetic-dust-collection-port/",
  "content":"\nNote: I moved all my woodworking posts to my new woodworking blog at fumblyworkshop.com.\n\nDust collection is a pretty big problem in my workshop; I've ignored it for a long time, but I decided I had to do something about it. My router table has built-in dust collection under the table and in the fence, but if I'm not using the fence, I make quite a mess in my workshop.\nLately, my friend Scott and I traded technology favors, I make 3D prints of his car parts and he designs cool stuff for my workshop. One of the things I asked him to design for me was a dust port I could use on my table saw and on my router table with the fence removed.\n3D Printing FilesYOu can find the 3D print files for this project on Thingverse.\nHere's what he came up with:\n\nIts a PLA dust port with a connector on the backside for the hose from my dust collector. The best part of it though is that it uses two of those rare earth magnets to hold the dust collection port to the cast iron top of my router table (and table saw).\nThose yellow and black parts connected to the dust port hold the rare earth magnets. When you twist the black knobs, the magnets lower to the base of the unit and make a magnetic connection to the iron tool top.\n\nHere's the underside of the magnet thingies; they sit flat on the table top, but when you twist the knobs, the rare earth magnets lower to make contact with those bottom plates. When that happens, it's locked to the table top and requires about 55 pounds of effort to move it. Enough strength to hold it in place while I cut something.\n\nHere it is attached to the top of my router table.\n\nTo remove it, simply twist the knobs in the opposite direction and it disconnects from the table.\nThe magnet thingies I used for this project are the Magswitch MagJig 60 Magnetic Woodworking and Welding Base Clamp Holder for Wood Working Supplies, Accessories, Tools and Equipment, Magnet Switch with On/Off Capabilities, 55 lb Holding Force. There's a lot of different options out there, but these were the righty size, price, and strength for my needs.\nFind the 3D print files on Thingverse at Workshop Dust Port with Magnetic Switch.\nEnjoy!\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Install Windows DLL Using Inno Setup",
  "date":"Fri Jun 27 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1751068800,
  "url":"/posts/2025/install-dll-inno-setup/",
  "content":"I recently wrote a Delphi application for Windows that implements a Windows Shell Extension which means I must distribute it as a DLL. I've used Inno Setup for a while now to create and publish Windows installers, but I'd never created one before for a DLL.\nI recently started to trust Google Gemini more and more for answers when searching for technical solutions, but when it came to figuring out how to make a DLL installer using Inno Setup, Gemini failed me multiple times. It seemed to understand the question and showed me detailed code blocks that supposedly solved my problem, but none of them work. For the most part, the code wouldn't even compile and, after modifying it so it compiled, never successfully installed the DLL.\nI finally found articles (no AI-generated stuff) that pointed to the correct solution, so I thought I'd post my findings to help others in the same situation.\nThe core of the solution is the following code in the project's setup.iss file:\n\nThere's a lot more to a complete Inno Setup file, but I want to focus on the things I had to change to install the DLL. Let me take you through the sections...\nSetup\n\nUninstallDisplayIcon: The project doesn't install with an app executable, so I can't point the installer at the app executable for the uninstall icon. So, I found some representative icon and included its file in the installer (see the Files section below).\nArchitecturesInstallIn64BitMode: I compiled my DLL only for Windows 64, so this tells Inno Setup to support a 64 bit install.\nPrivilegesRequired: I'm registering a DLL, so the installer must run with admin privileges. This enables Admin install and is the default, but I set it anyways just to make sure.\n\nFiles\nSource files:\n\nmydll.dll: The compiled DLL\nmydll.ico: The uninstaller icon for the project\n\nRun\nCalls the 64-bit version of RegSvr32.exe and instructs it to execute the DLL's UpdateRegistry code. This code adds the entry for the DLL's shell extension in the Windows Registry.\n\nUninstallRun\nWhen uninstalling the DLL, calls the code from the section above to delete the shell extension registration Registry key.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi"
  
  ]
  },

  {
  "title": "Delphi Single Instance App With Runtime Parameters",
  "date":"Sat Jun 14 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1749945600,
  "url":"/posts/2025/delphi-single-instance-app-runtime-parameters/",
  "content":"After I published Subdirectory Copy version 1.1 (v1.1.1.1), I realized that I should probably update the application so users can launch the application by double-clicking on one of the application project in Windows File Explorer (or its alternatives). I quickly added support for a single runtime parameter (the full path pointing to the project file):\n\nNext, I modified the Inno Setup installer installer to register the file extension handler for the project file (*.scpy):\n\nThat all works (although I haven't published that version of the app yet), but then I realized I had a potential issue. What if the user ran two instances of the application at the same time? Thinking through it, it would actually work. I started thinking through it and realized that wouldn't be too much of a problem since even though multiple versions of the app could be copying the same files to different drives or copying multiple filesets to the same drive, since TeraCOpy was doing all of the work, I didn't have to worry about it. TeraCopy would succeed or crash and it wasn't my responsibility (I don't expect TeraCopy to crash, I expect it would handle it just fine).\nTo avoid any confusion, I decided to modify the application so only a single instance can run at any time. Doing that required being able to handle both launching a second instance by itself or launching a second instance with a runtime parameter (the path the project file to open).\nExcellent Source ArticleAs I tried to figure this out on my own, I discovered How to run a single instance of an application on the Delphi Dabbler site. The article does a great job of explaining the process and is chock full of source code and I learned how to make it work using that article. Kudos to @delphidabbler for all  his work on the article.  I published a complete sample project from that article's code, you can find it at Delphi Single Instance Demo.\nBlocking a Second Application Instance\nBlocking a second Delphi application instance from running is easy to implement in Delphi.\nFirst of all, you define a unique name for your application:\n\nNext, on application launch, assign that name to your application in the application's main form code, overriding the form's CreateParams procedure:\n\nNote: Refer to the full implementation of this in Delphi Single Instance Demo; there's a little more to this than what I show here. The sample app has complete context and code.\nNext, in the application project code (the project's .dpr file), check to see if that window (with the assigned name) already exists before initializing and launching a new instance of the application:\n\nIts really as simple as that.\nPassing Runtime Parameters to the Initial Instance\nThere are two things missing from the previous example:\n\nActivating the existing instance (making it visible and bringing it to the forefront) before closing the second instance.\nPassing any command-line parameters (runtime parameters) from the second instance to the existing instance.\n\nThe demo application I published (link above) shows the complete code for this and you'll find a complete description of what's happening in the code in the Delphi Dabbler article.\nActivating the Existing Instance\nIts all fine and dandy to kill a second instance when launched, but for the best experience, you should automatically switch to (Activate) the original instance when you do so. The sample project does this by sending a message to the initial instance instructing it to display its application window:\n\nThis is the code that responds to the message, located in the application's main form code:\n\nHere's what the code does:\n\nThe IsIconic asks whether the application is minimized; if it is, it restores (opens) the application window.\nIf the application is not visible, it makes it visible\nBrings the application to the forefront\n\nThe result of this is the application window appears on the screen (no matter what its original state was) and, to the user, it feels like it launched just like the user expected.\nPassing Command-line Parameters\nTo pass command-line parameters between a second application instance to the initial instance, the application sends a message between the application instances passing the command-line parameters from the second instance in the body of the message. Here's the code that sends the message between application instances&quot;\n\nThe code builds a data object containing the list of strings (command-line parameters) and sends it to the original instance using SendMessage. Here's a Embarcadero/Delphi blog post that describes this process.\nIn the application's main form, you must implement code to respond to the message:\n\nIn this example, the ProcessParam function represents code in your app that does something with those parameters.\nPutting it All Together\nAll there's left to do is update the code that launches the application do:\n\nCheck to see if an instance is already running\nPass any command-line parameters from the second instance to ",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Published Subdirectory Copy v1.1",
  "date":"Fri Jun 13 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1749859200,
  "url":"/posts/2025/subdirectory-copy-v1.1/",
  "content":"When I created my Subdirectory Copy application, my use case was copying a single set of files to a flash drive. As I got closer to releasing the product, I started thinking more about how users would use it and I realized that the application had to be able to manage multiple filesets for copying.\nEven though my new car offers only a single flash drive interface for playing music files, my previous car (an Audi Q7) had two SD card slots that I could play music from. So, as soon as I published version 1 of the application I immediately started working on version 1.1 (v1.1.1.1) which allows users to save the application's copy configuration to an external Project file. With that in place, users can switch between them to copy multiple filesets to external drives.\nDownload Version 1.1You can download the project's source code and installer from GitHub or directly from Fumbly Diddle Software's CDN.\nHere's the application's new home screen. Notice that I added a menu to the application and moved the Copy button to the bottom of the screen.\n\nImplementation Details\nThe first version of the application stored all of its settings in the Windows Registry. This worked great and allowed me to quickly bring the application to market. For this new version, I pulled the Root directory path and Source directory list from the registry and saved them to the Project file.\nProject files have a .scpy extension, but under the covers they're just a standard Windows .ini file:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "TechSmith Windows Snagit Stops Loading or Capturing",
  "date":"Thu Jun 12 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1749772800,
  "url":"/posts/2025/techsmith-snagit-not-loading-windows/",
  "content":"A few weeks ago, Snagit stopped launching its capture window on startup (yes, I had automatic launch at startup configured) and stopped being able to capture accurately 90% of the time.\nI've been a Snagit customer for decades and use the product almost every day, at home and at work.\nI don't know exactly when it stopped working, but all of a sudden I noticed that the Capture widget wasn't on my screen. If I launched Snagit directly, it would launch and stay running, but every time I rebooted Microsoft Windows, no Snagit capture widget.\nAfter a couple of weeks of manually launching Snagit, I noticed that the application would only work successfully about 10% of the time. The other 90% of the time, capturing would either only capture the whole screen or, if it did recognize I wanted to capture a application window, it would capture some other rectangle than the one I was trying to capture.\nSo frustrating!\nI own three licenses, I run Snagit on three computers at home, so I quickly fired up Techsmith technical support and created a ticket for each problem. Not expecting much, product support is so useless it seems lately, I quickly heard back from Techsmith support within about 24 hours. The support staff was very responsive and provided a lot of guidance. That was just awesome!\nAnyway, I'm not going to detail all of the steps we took to figure out the problem, I'm just going to jump to the solution:\nDell Display Manager\nApparently, the latest version breaks a lot of other applications. Screen capture utilities is one of the affected app categories.\nI uninstalled Dell Display Manager, rebooted my system, and all of my Snagit issues went away.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Simplifying Copying Music Files to a Flash Drive",
  "date":"Thu Jun 05 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1749168000,
  "url":"/posts/2025/copy-music-files-flash/",
  "content":"In my previous post I discussed options for playing music files from an SD card or Flash drive on some automobiles. One of the things I didn't mention was how to get those music files onto the drives.\nI have almost 30,000 music files, and there's no way any memory stick can hold all of the files with the automobile's music player recognizing the drive. Most automobile music players have capacity and/or file count limitations that make that impossible. So, in order to play my music from an SD card or Flash drive, I could only copy a subset of the files to the drive.\nNow, that task isn't very hard, I can insert the drive into my computer and drag any music files I wanted onto the external drive. However, updating the files when an artist releases a new album becomes a problem.\nI could write a Windows command file (batch file) and write a bunch of Windows copy or robocopy commands to copy all of my favorite artists' music to the drive. That would work, but, I don't know, I don't want to have to manage the code in that file.\nTo resolve this, I created a simple Windows application that automates this whole process for me. The application is called Subdirectory Copy (SubCopy) and I published it through Fumbly Diddle Software and the Fumbly Stuff GitHub Repository.\nNote: The application uses the free TeraCopy utility to manage the copy process; so you must have TeraCopy installed to use this application. If you find you like the capabilities TeraCopy provides, please consider buying a license.\nTo use the application, you start by populating the root directory where you have your music files. I've used iTunes for decades, so all my music is in my Itunes Media Music directory (C:\\Users\\john\\Music\\iTunes\\iTunes Media\\Music). Next, you drag all of the artist folders you want to copy to an external drive. This configuration looks like this in the application:\n\nOnce you have everything setup, click the Start button in the UI. The application opens a window that lets you configure options for the copy process.\n\nWhy TeraCopy?\nOne of the reasons I used TeraCopy to manage the subdirectory copy process is that it offers command-line options that allows me to easily control the copy process. I simply didn't want to have to write code to handle every possible failure scenario.\nTeraCopy allowed me to write a series of source directories to a text file, then pass that file to the TeraCopy application to copy theall of them to the target drive in order. To do this, the SubCopy application creates a temporary file in the Windows temp directory (%temp%) and passes it to TeraCopy to complete the operation.\nHere's what the file looks like:\n\nTeraCopy supports different operation types:\n\nCopy\nMove\nTest\n\nWhich allowed me to offer more options without writing much additional code. TeraCopy also supports a variety of copy options:\n\nSkip All: Skip all existing files.\nOverwrite All: Overwrite all existing files.\nOverwrite Older: Overwrite files if the source is newer.\nOverwrite Different Size: Overwrite if sizes are different.\nRename Copied File: Automatically rename source files with conflicting names.\nRename Destination File: Automatically rename target files with conflicting names.\n\nWhich also allowed me to offer users more options without writing much additional code.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows",
  
    "Automobiles"
  
  ]
  },

  {
  "title": "Outlook Pastel Categories macOS",
  "date":"Wed Jun 04 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1749081600,
  "url":"/posts/2025/outlook-pastel-categories-macos/",
  "content":"A few weeks ago, I launched Microsoft Outlook on my work MacBook and noticed that the Calendar view displayed categories in pastel colors. I don't know what happened and I know I didn't do anything, but those had always been solid colors. The pastel colors were really annoying and made it hard to see my appointments the way I wanted to see them.\nI did a quick search online and couldn't find any current documents that provided a solution to this problem. Poking around in Settings (both in Outlook and in macOS), I couldn't find anything I could do to revert the colors to solid.\nI submitted an IT ticket with my employer's help desk and didn't get anywhere. Even with the support technician controlling my system and poking around in the same places I did.\nAt this point, I gave up and realized I was stuck with these ridiculous pastel colored categories in Outlook.\nAround the same time, I noticed that my Zoom plugin for Outlook no longer worked. As I poked around looking for a solution to that problem, I found a way to fix the pastel categories issue.\nIn the Outlook for macOS Help menu, there's an option called Clear Application Data :\n\nSelect that menu item and Outlook will open the following dialog:\n\nNext, select the option to clear data for Experimental Features and click the Clear button.\nWhen I did this and restarted Outlook, all my solid category colors came back; the pastels are gone.\nPostscript\nI made the change described above and it worked for me, but only temporarily. Sigh. Clearing experimental features clears them from the local config, but then Outlook pulls them down from the server some time later. So, the next morning when I started outlook the pastels were back.\nI performed the reset steps again, restarted Outlook,  and the pastels came back a few minutes later.\nWhat a horrible, horrible experience. Why would Microsoft even consider forcing pale/muted colors for categories when I've used solid colors in Outlook for DECADES. It's a ridiculous change and as far as I can tell there's no getting around it. WTF?\nSearching around I found a Microsoft Feedback site with feedback called Calendar Category Colors Only Pastel Now!. Follow that link and make your voice heard if you hate this 'feature' as much as I do.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Outlook"
  
  ]
  },

  {
  "title": "Acura MDX Play Music on USB Flash Drives",
  "date":"Wed Jun 04 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1749081600,
  "url":"/posts/2025/acura-play-music-usb/",
  "content":"In Audi Q7 Drive System Failure I described a problem I had with an Audi Q7 I owned. As soon as I got it back from the dealer (after waiting almost 6 months for them to fix it), I immediately traded it in for a 2025 Acura MDX. The replacement engine they installed in the car had 10,000 more miles than the one that broke, so I knew it was a ticking time bomb.\nOne of the features the Audi had I'm happy to say is also a feature of the Acura MDX: the ability to play music files from SD cards (Audi) or USB Flash drives (Acura). When I'm on a longer trip, I like to put on one of my favorite bands and listen to a bunch of albums while I drive. This feature allows me to quickly locate the artist I want to play without having to dig out my phone and navigate around the YouTube Music app. It's a pain in the ass to do that in YouTube Music, I either have to pick a playlist (which I never want to do) or add multiple albums to a queue. The memory card approach is best for this.\nAnyway, the Acura MDX Manual says you can play music from USB drives, but provides no information on how to do it:\n\nThe USB port (3.0A) is for charging devices, playing audio files, and connecting compatible phones with Apple CarPlay or Android Auto.\n\nThat's it, I can play audio files from a flash drive, nothing more.\nKnowing what I know about cars and memory sticks/drives, I know that there are four things that affect whether you can play music from an external drive:\n\n\n\nIssue\nDetails\n\n\n\n\nDrive Format\nThe computer system in the car playing the music files (the media player) may not be as up to date on drive configurations. It may support only a subset of the available options.\n\n\nMaximum number of files\nThe media player may only have enough memory to manage the file system for a specific number of files. My old Audi supported a maximum of 10,000 audio files on a SD Card (it may have been 20,000, I don't remember).\n\n\nDrive Capacity\nOn top of the maximum number of files supported on the drive, the media player may support a limited capacity.\n\n\nFile Format\nMedia players are limited by which drive formats they can read.\n\n\n\nSo I set about figuring out how to do this and I was able to get it to work. I'm sharing the details here to help other Acura MDX owners in the same situation.  I didn't get all the answers I needed, but here's what I have.\n\n\n\nIssue\nDetails\n\n\n\n\nDrive Format\nReading different articles on the Internet, I found that the Acura MDX supports the FAT and FAT32 file formats. I tested drives formatted with each and they worked for me. Note: I saw some articles that mentioned support for exFAT, but that didn't work for me.\n\n\nDrive Capacity\nI tested 16GB, 32GB, 64GB, 128GB, and 256GB drives. Everything except for the 256GB drive worked in my MDX.\n\n\nFile Format\nI read somewhere that Acura vehicles &quot;generally support MP3, WMA, and AAC files&quot;. I only tested MP3 files and they worked great for me.\n\n\nMaximum number of files\nI wasn't able to find any reference for this. I put more than 6,000 music files on a drive and the media player read them just fine. I assume the real limit is 10,000 files but I've not tested it yet.\n\n\n\nThat's it, that's all I know. I hope this helps you.\nPerhaps Acura will someday publish the actual details for this so their customers don't have to figure it out themselves. How hard would it be to add a table to the manual that covers these 4 requirements/limitations?\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Automobiles"
  
  ]
  },

  {
  "title": "TeraCopy Disable Check Free Space Check",
  "date":"Fri May 23 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1748044800,
  "url":"/posts/2025/teracopy-disable-check-free-space/",
  "content":"I purchased a new car recently, and I'm trying to setup a Flash drive with a lot of (but not all) of my music so I can listen to my favorite artists while driving and not need Pandora or Youtube Music. I'm building a simple utility I can use to refresh the files on the flash drive when I pick up something new for a particular artist or when I want to add a new artist's music to the drive.\nRather than directly managing the process of copying thousands of files, I decided to spawn a copy of the TeraCopy utility to do all that work for me. I've used this utility for years and purchased a license a long time ago. It's an excellent utility for managing multiple file copies automatically and it offers more flexible options for retrying, renaming, and other issues that pop up on Windows file copies.\nAnyways, TeraCopy provides excellent command-line options I knew I could use to successfully drive TeraCopy from my utility (I'll write more about this later).\nI finished the utility and everything was working great until I tried to copy the files to the flash drive a second time (refreshing the contents and overwriting only older versions of the files). As soon as my utility launched TeraCopy, TeraCopy immediately complained that &quot;more space is required&quot; to complete the copy.\nWell, sure, it looks that way, but I knew if TeraCopy tried to actually copy the files, it would see that it did have enough space to complete the copy.\nSo I looked around and couldn't find anything online that explained how to fix this issue. The CodeSector web site has an AI Support agent, so in desperation I asked it for help:\n\nI'm trying to copy a bunch of files to a flash drive and many of those files already exist. So I'm overwriting only older files. When I do this, TeraCopy reports &quot;More space is required&quot; when it really isn't. How do I disable that check or make the app do the copy anyway?\n\nAnd the agent quickly replied with the solution:\n\nOpening up Explorer, I navigated to the application data folder and found the configuration file.\n\nAfter a quick edit, changing the highlighted value from 1 to 0 (as shown in the figure below), everything worked as expected. I'm so happy they had a solution for this.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows",
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "NeoPixel Stick Mounting Issues",
  "date":"Wed May 14 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1747267200,
  "url":"/posts/2025/neopixel-stick-mounting-issues/",
  "content":"In yesterday's post about mounting Adafruit NeoPixel Stick devices in a line, I made the following comment: &quot;But, the folks at Adafruit didn't feel the need to make this easy.&quot; For this post, I thought I'd explain why I said that.\nWith a lot of hobbyist electronics boards and accessories, in many (most) cases, it feels to me like the Engineers who design these products focus solely on the capabilities offered by the device (whatever it is) but not on how the device will be used in the underlying project. I notice this more and more frequently and I expect I'll write a lot more on this topic here (my blog).\nLooking at the NeoPixel Stick - 8 x 5050 RGBW LEDs - Cool White - ~6000K, its a great device - mostly because it does exactly what I need/want it to do. For the project I wrote about yesterday, I needed a long, straight, solid strip of LEDs. Having 8 NeoPixel LEDs lined up close together plus the ability to fit them together in a longer line (using three of the devices in series) was a bonus. The problem though, is actually doing that.\nTaking a look at the product, it's pretty much as small as it can possibly be; the folks at Adafruit did a really good job making the product as small as possible. I imagine they did this in order to allow the product to be used in as many possible scenarios as possible.\n\nImage credit: Adafruit. (cropped by me)\nMaking the product bigger, in order to offer simpler or more flexible options for mounting the product, could potentially eliminate the product's ability to be included in some projects.\nWhen I started complaining to myself about how hard it was to connect three of these boards together, I started thinking of ways to keep the solder pads for people who want to use them (I find it extremely difficult to solder wires to solder pads, you need at least three hands) but drill holes in the pads so I can solder wires using through holes if I wanted (much easier to solder).\n\nImage credit: Adafruit. (cropped by me)\nI thought that was an amazing idea, until I looked at the front of the board. Right behind the solder pads on each end of the board is a NeoPixel. There's not room for through holes. Sigh.\nThinking through this more, what if I wanted to sew these into something? There's the two mounting holes, but in order to securely sew this device into an article of clothing, I'd need holes on both sides of the board (top and bottom when looking at the images) so I can ensure the position of the board no matter how the material folds/flexes.\nSee what I mean?\nHere's what I think Adafruit should do with this device. Make it a little wider, not much, then add needle sized holes on each side that someone can use to stitch this device into clothing.\n\nKeep the solder pads on the end if they want, but add through-hole connections so I can solder wires securely to the board without needing three hands.\nWith those small changes, the device stays as powerful it is today from a capabilities standpoint while at the same time becoming more flexible in mounting and connection capabilities.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)",
  
    "Project Builds"
  
  ]
  },

  {
  "title": "Mounting Multiple NeoPixel Sticks in a Line",
  "date":"Tue May 13 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1747180800,
  "url":"/posts/2025/neopixel-stick-mounting/",
  "content":"This post describes a 3D printed device I use to mount multiple Adafruit NeoPixel Sticks together in a line. I had a friend create it for a project I'm working on.\nI'm building a Throttle Gauge for a friend of mine. He has a Porsche Boxter he's stripped down to the bare minimum that he uses for Autocross racing. He has a camera mounted on the roll bar that records every run, and he wants to be able to include the throttle position and brake activity on the recorded video. To do that, he'll attach this microcontroller controlled throttle gauge to the throttle and brake and measure the status of each in realtime during a run and display status on a line of LEDs.\nTo build this throttle gauge, I needed a line of LEDs that I could individually control from a microcontroller. The Adafruit NeoPixel Sticks are perfect for this; I selected the NeoPixel Stick - 8 x 5050 RGBW LEDs - Cool White - ~6000K. I just needed a simple way to connect them all together in series. I'll explain how I did that in a minute.\nFor this project, I needed 20 or so LEDs for the throttle gauge; adding 4 for the braking indicator, three 8 LED sticks provided the perfect number of LEDs.\nWhen you look at the back of the NeoPixel Stick, you'll see that the device offers two mounting holes plus solder pads on each end for power, ground, and a single data connection to the microcontroller.\n\nImage credit: Adafruit. (cropped by me)\nSolution\nWhat I needed was something I could use to line all of the strips together in series, like this: a simple mounting board for three NeoPixel Sticks.\n\nDouble the HelpThis device helps me two different ways. I used it to hold the NeoPixel Sticks in place as I soldered them, then I turned them over and mounted them LED out for the throttle gauge.\nSoldering\nI started by mounting the NeoPixel Sticks upside down on the mounting board (NeoPixels facing down) so I could keep them in place as I soldered them together. Next, I melted some solder on each solder pad as shown in the figure.\n\nWith that solder in place, it was a simple process to solder connecting wires between the solder pads paired devices. Plus, I connected some wires to the input pads so I could easily wire them into my microcontroller circuit.\n\nI lied, it wasn't a simple process to solder everything together, it was a royal pain. I hate doing this kind of soldering. But, the folks at Adafruit didn't feel the need to make this easy.\nAssembly\nNext, I used nylon M2 bolts to secure the NeoPixel Sticks to the mounting board. Since I had the soldered connections on the back, I added two washers to give the soldered connections some room.\n\nAnd here's the complete assembly with nuts on the back holding the mounting board to the NeoPixel Sticks.\n\n\nyes, I know, they're slightly out of alignment. I'll fix that.\n3D Printing Files\nI published the 3D printing files for this device on Thingverse: Adafruit NeoPixel Stick Mounting Board 3 Sticks\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)",
  
    "Project Builds"
  
  ]
  },

  {
  "title": "FoxAlien Masuter Pro Spindle",
  "date":"Mon May 12 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1747094400,
  "url":"/posts/2025/foxalien-masuter-pro-spindle/",
  "content":"Recently, I purchased a FoxAlien Masuter Pro CNC Router for my workshop. I assembled all the parts and started testing the unit. Everything seemed to work, except for the spindle. I couldn't get the included software to turn the spindle on.\nI pulled it out of the unit and applied 5V DC to it and the spindle motor worked just fine.\nNext, I checked continuity on the two spindle wires on the CNC Router; all good.\nThere's a switch on the Controller and the instructions tell you to move the switch to the right as shown in the figure below.\n\nWell, it turns out there's an error in the FoxAlien Masuter Manual. The switch must be set to the left. As soon as I made that change, the spindle started turning on and off as expected.\nSadly, the post I found that explained the error was in 2024, so apparently FoxAlien isn't paying attention. They should have fixed the manual or at least published an addendum pointing out the error.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Mounting Breadboard-friendly NeoPixels",
  "date":"Sat Mar 15 2025 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1742083200,
  "url":"/posts/2025/mounting-neopixel/",
  "content":"I build a lot of projects using Adafruit's NeoPixels. They dramatically simplify the process of wiring multiple LEDs into a project, requiring only three wires between each NeoPixel rather than two wires and a resistor to each LED. This article explains an issue I discovered with mounting Breadboard-friendly RGB Smart NeoPixel in a project and the solution I found for resolving it.\nThe Problem\nThe breadboard-friendly NeoPixels (BFN) have mounting holes, but it seems to me that the holes are designed for sewable projects (where you want to sew a NeoPixel to a piece of clothing). Here, let me show you.\nThe BFN has two of what looks like mounting holes you can use with a bolt or a screw to mount the NeoPixel on a board. However, when you insert bolts into the holes from the top, due to the component orientation on the top of the board, the bolt heads won't sit flat on the top of the board. This makes it impossible to mount the device using bolts.\n\nFlipping the board over, you can see the issue. The NeoPixel LED sides bump right up against the bolt holes, causing the bolts to skew as shown in the previous image.\n\nThe Project\nRight now I'm working on a wall mounted version of the Word Clock NeoMatrix Wi-Fi Desktop. As I planned for this project, I decided to use BFNs arrayed in a grid mounted on a panel. For the panel, I used black acrylic and arranged the BFN in a grid using mounting holes drilled (burned, cut, whatever) in the panel.\n\nAs soon as I tried to mount the first NeoPixel I realized my problem. If I straighten out the bolts so they'll fit in the holes on the panel, I had to rest at least one of the bolts on top of the NeoPixel LED.\n\nThat could work, but at the same time I was worried about tightening the bolt too much and crushing the NeoPixel.\nI investigated a variety of options, like printing a little spacer to allow me to use the bolt but not crush the NeoPixel, but my 3D printer wouldn't print anything that small. I also investigated cutting the side off a stack of washers, but there's not enough room on the board to do that.\nSo frustrating.\nThe Solution\nI invested recently in a high quality 3D printer and have been trying to learn how to use the available design tools to design stuff for my projects. I got pretty good with TinkerCad, but quickly bumped up against limitations in the tool. I decided to spend some time learning Fusion 360 since it seems pretty capable to me.\nI discussed my NeoPixel mounting issue with a colleague and he offered to help me create something to solve this issue. He fired up Fusion 360 and gave me a demo of how it works then quickly threw together a NeoPixel Mount that worked perfectly for my project. Here it is.\n\nThe component mounts to the panel using M2x6mm bolts (steel), then the NeoPixel sits on top. The device is really small, so there's no room to securely attach the NeoPixel to the top of the component. I'll have to use a glue gun to hold the NeoPixel in place. That works for me considering what my other options are here.\nNeoPixel Riser MountMy colleague published Neopixel Riser Mount design on Printables so you can use it in your own projects. \nOne of the cool things about Fusion 360 is that you can use it to do parametric modeling. This allows you to store dimensions as parameters in the design then tweak the values assigned to those parameters to quickly adjust the design. My colleague designed the component with a height of 5mm, but set that as a parameter in the design. So, if I decided I needed a taller mount, I could just adjust the parameter and the design would adjust accordingly. For example, here's the parameter editor dialog, allowing me to change the height from 5mm to 10mm.\n\nAnd here's the updated design at 10mm height:\n\nImplementation\nHere's the acrylic panel with a bunch of these components mounted. When I finish the project, I'll show you what the complete project looks like.\n\nGetting the NeoPixel Riser Mount\nMy colleague published the design on Printables as Neopixel Riser Mount so you can use it in your own projects.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)",
  
    "Project Builds"
  
  ]
  },

  {
  "title": "USB 3.0 Cable Power Switch",
  "date":"Sat Mar 01 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1740873600,
  "url":"/posts/2025/usb-3.0-cable-power-switch/",
  "content":"On a couple of projects lately I found myself repeatedly plugging and unplugging microcontrollers to/from my development system. This happens most frequently when writing faulty code for an ESP32 device and, when the compiled code runs on an ESP32, the code Panics and repeatedly reboots the device - panicking every time it restarts.\nI also noticed that for some Microcontroller projects, like the M5Stack M5StickC-Plus  I can't leave the device plugged in very long if I want to deploy a new version of the code to the device; for some reason it regularly disconnects from the computer. I often must unplug the device and plug it back in again during the compilation step so it's in the right state when the Arduino Compiler's ready to deploy code to the device.\nThis started me looking for an USB cable switch that I could use to just disconnect power from the device but leave the cable plugged in between my desktop computer and the microcontroller device. I found quite a few online and even bought one, but they tend to be short cables with a switch in the middle which doesn't work for my use case. My development system is a massive tower computer sitting on the floor under my desk and a cable that short wouldn't reach the top of my desk with enough room to not pull the microcontroller off of the desktop with the weight of the cable.\nSo, I decided to build my own.\nComplete Project on InstructablesI published this project on Instructables as USB 3.0 Cable Power Switch.\nHere's an image of the completed project.\n\nI found some panel mount USB 3.0 ports and a double throw single pull (DPST) switch and got to work. First I designed a panel for the switch and printed it. I knew I'd ultimately build a wooden enclosure around it, but haven't done that yet. Here's an image of the panel, USB ports, some wires, and other stuff:\n\nNext, I mounted the USB ports to the panel\n\nAnd finally wired everything together and added the switch.\n\nI've been wanting to publish something on Instructables, so I made this my first project: USB 3.0 Cable Power Switch.\nI'll finish the enclosure for it this week and post some pictures.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Project Builds",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Phishing American Express Message Ready to View",
  "date":"Fri Feb 21 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1740182400,
  "url":"/posts/2025/phishing-american-express-message/",
  "content":"I received an email message the other day that seemed to be from American Express, but wasn't.\nDefinitely a Phishing EmailThis message, for a lot of reasons, is not from American Express and you shouldn't click any of the links in the message.\nThe message said it was from &quot;American Express Customer Care&quot;, but I've never received a message from American Express Customer Care. When you look at the message, you notice that Outlook blocked the images in the message. If the message had actually come from American Express (it didn't) the images automatically appear since I've already allowed image files from AmEx.\n\nLooking at the actual email for the message, I saw the following:\n\nThey tried to make it look like it came from American Express, but the sender domain is parcelhub.com.my which is definitely NOT from American Express. Looking at the domain, it seems that this is ParcelHub instead which seems like a weird redirect.\nLooking at the link behind the View Message button, the link there points to https://destinyeshop.com which, again, is not American Express.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "ESP32 Request Repeater With Sleep",
  "date":"Mon Feb 17 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1739836800,
  "url":"/posts/2025/esp32-request-repeater/",
  "content":"In my previous post I described how to put an ESP device to sleep (allowing it to wake up later). I used a sample sketch I created, ESP32 Request Repeater (HTTP), to show how it works.\nThe sample sketch sends a HTTP to a remote host, then puts the device to sleep (deep sleep) with instructions to wake up two minutes later to do it again. I realized then I would probably make a TLS (HTTPS) version of the sketch and publish it as well. Well, I published it, and this post highlights the differences between it and the HTTP version.\nESP32 Request Repeater (HTTPS)All the code for this project is online at ESP32 Request Repeater (HTTPS).\nBoth versions (HTTP and HTTPS) of the sketch:\n\nTells you how many times it's woken and made (or tried to make) a request\nWaits for 30 seconds so you can upload sketch updates to the device\nConnects to the Wi-Fi network\nSends the request (this version sends the request using TLS (HTTPS))\nPuts the device to sleep for SLEEP_DURATION_MINUTES\n\nSo it's the exact same approach except for the more secure nature of the request.\nInitialization\nThe initialization section of the code has only a few changes, mostly additions:\n\nThe code has the following changes:\n\nAdded the WiFiClientSecure library which implements a client object the sketch uses to create an HTTPS request.\nAdded the Certificate Authority (CA) certificate file cert.h required to enable secure communications with the remote host using TLS (HTTPS). I wrote more about this in ESP32 Connect Using HTTPS\nChanged the HTTPClient variable from http to https\nCreated a new client object using WiFiClientSecure.\n\nBeyond those simple changes, the remaining changes are in the callRemoteHost() function described below.\nSending the Request\nIn the sketch, I enhanced the callRemoteHost() function to use the client object to manage the secure connection to the remote host:\n\nThe differences from the HTTP version are:\n\nAssigning the CA cert to the client object\nPassing the client object (well, a pointer to the client object anyway) when begining the request\n\nOtherwise it's essentially the same code.\nOne other difference is that the sketch checks the status of the call to begin and only tries to send the request when that succeeds. I don't know where I pulled that code from, I imagine it would work as well without it.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Cloud Function Certificate Issue",
  "date":"Mon Feb 17 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1739836800,
  "url":"/posts/2025/cloud-function-certificate/",
  "content":"After publishing my M5StackC-Plus Cloud Function Execution example, I used it for about a week before it just stopped working one day.\nI tried opening my garage door with it a couple of times and it failed every time. So I pulled out my smartphone and opened my custom garage opener app and it worked just fine.\nSigh.\nSo, it wasn't a network issue, and cloud function used by the sketch works just fine (the mobile app calls the same cloud function).\nIt didn't take me long to start thinking about security as the cause for this issue. I fired up my browser of choice, navigated to the cloud function and clicked the public URL for the function. Following the instructions I'd written in ESP32 Connect Using HTTPS I opened up the root Certificate Authority (CA) certificate used by the cloud vendor's functions service and realized that it was different than the one used in the sketch.\nI downloaded the cert, converted it into Arduino source code using Cert2Arduino, built and deployed the sketch, and discovered that this fixed the issue\nI don't know whether cloud function provider suddenly decided to switch the CA certificate or whether what happened was part of regular cycling of the certificates. It also could be that I was accidentally hitting the same server and a load balancer suddenly sent me to a different one (with a different CA cert).  I'll watch this for a while and see if it happens again and let you know.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Putting an ESP32 Device to Sleep",
  "date":"Sat Feb 15 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1739664000,
  "url":"/posts/2025/esp32-sleep-http/",
  "content":"While playing around this week with a hardware project, I decided to spend some time learning how to use Sleep modes in an Arduino project on an ESP32 device. It turns out that it's not that hard to do, but you really have to pay attention to a couple of things as you code your project. In this post, I demonstrate how to build an Arduino project that sends a HTTP request to a remote server, puts the device running the sketch asleep for a few minutes, then wakes up and does it again until the device loses power.\nESP32 Request Repeater (HTTP)All the code for this project is online at ESP32 Request Repeater (HTTP).\nLets take a look at the code.\nInitialization\nThe sketch uses the standard Arduino/ESP32 WiFi and HTTPClient libraries. New for me is the esp_sleep.h library that I needed to implement sleep and wake capabilities in the sketch.\n\nThe final line in the code block loads configuration settings from an external file (a file that isn't included in the Github repository). This allows you to configure the sketch as you need, but also refresh the repository contents whenever I publish updates and not overwrite the config. Read the instructions in the repository to understand how to create and populate the config file.\nNext, the sketch creates a few constants and variables used by the sketch:\n\nThe first two lines define constants holding the Wi-Fi network SSID and password as character (char) array pointers built using the corresponding settings from the config file.\nThe minutes2Microseconds constant allows the sketch to convert the config file's SLEEP_DURATION_MINUTES minutes value into the microseconds value the sketch needs to tell the device how long to sleep.\nThe restartCounter variable is special because of the RTC_DATA_ATTR that precedes the definition. This variable contains a counter used by the sketch to track how many times the device wakes itself up to run the sketch. RTC_DATA_ATTR means realtime clock (RTC) data attribute which is essentially a compiler directive that instructs the compiler to store this value in the RTC memory space. When stored there, the value isn't lost when the device powers down.\nFinally, the HTTPClient object is part of the ESP32 SDK and defines a client object the sketch uses to connect to remote hosts.\nThe Code\nI'm going to start with the loop() function. For this particular sketch, there isn't any activity that happens in the loop function since the sketch starts, does its stuff, then powers down. The device never executes the loop() function, so therefore it's empty:\n\nRemember when I mentioned that there were a couple of things you had to pay attention to in your sketch? That's one of them, whether there's any work for the device to do repeatedly in the loop() function before going to sleep.\nNow, because of that, everything happens in the setup() function. Here's the full code for the function, I'll break it down and explain it to you after you've had some time to look at it.\n\nAlright, so the code starts with the standard stuff I put in every Arduino sketch, code that starts Serial and prints some stuff to the Serial Monitor.\nNext, the sketch makes sure that it at least has values for the Wi-Fi network SSID and associated password. I really should validate the other configuration properties, but I got lazy here.\n\nTo let the user know how many times the device awoke from sleep, the sketch increments the restartCounter variable - remember, this value is stored in RTC memory so it doesn't disappear when the device goes to sleep. Once it's completed that, it writes the current counter value to the Serial Monitor (skipping the first time).\n\nAnd, to help you understand what woke up the device, I added a call to a little function that writes the reason to the Serial Monitor. It does this based on the value returned from the call to esp_sleep_get_wakeup_cause().  I basically looked at the docs docs and built a simple case statement that writes a text message to the Serial Monitor based on the esp_sleep_wakeup_cause_t value (numeric).\n\nAlright, here's the second place where you really have to pay attention to what you're doing. When I started on the sketch and got everything working, the next morning I added some things and moved some stuff around. As I tried to deploy the updated sketch to the device, it kept losing its connection to the Arduino IDE. After fussing at it for a while, thinking that the board was fried, I realized that what was happening was expected.\nAs I have the sketch configured: it connects to Wi-Fi, sends an HTTP request, then powers off the device for two minutes before doing it all again. The device wasn't broken, the window between the device powering up and shutting down again was so small that there was limited opportunity for me to sneak a code update onto the device.\nThe best solution to this is to start the build and deploy step in the Arduino IDE then plug the device in right before compilation ends and deployment begins. By doing that you should be",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "ESP32 Parroting Web Server",
  "date":"Fri Feb 14 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1739577600,
  "url":"/posts/2025/esp32-parroting-web-server/",
  "content":"I'm working on a version of my Pumpkin LED Controller for the Unihiker M10 single board computer. Web and mobile apps have a variety of issues when connecting to a web server running on an ESP32 device (as I wrote about in Accessing an Arduino ESP32 Web Serverand Pumpkin Controller Native Apps for Windows) and I think a device like the Unihiker may provide a way around them.\nAnyway, I have the first version of the Python app finished and as I started thinking about testing the app, I realized that all of my pumpkin LED devices are all in storage and zip tied to some fake pumpkins. I didn't have any spare hardware devices lying around (it uses a special 5x5 LED matrix I had to order), so I decided to write a little sketch that acted as a simple web server that parroted every request it received. With that sketch running on an inexpensive ESP32 device, I could test my python program without needing the custom hardware.\nESP32 Parrot ServerYou can find all of the code discussed in this post on Github in ESP32 Parrot Server. The code you need to configure and deploy the sketch on an ESP32 device is in the repo.\nThe code is really simple and easy to configure. I abstracted the Wi-Fi credentials and local hostname into a separate configuration file so if I make changes in the future, you can apply them without having to reconfigure the sketch.\nWhen you run the sketch, the Arduino IDE Serial Monitor displays a running commentary on the incoming requests:\n\nThis allows me to watch incoming requests as I test and troubleshoot the code making the requests.\nThe MDNS line in the output indicates that it registered the hostname on the local network, so the application that sends requests to the sketch can access the server using the hostname (in my example parrot) and .local like this: http://parrot.local.\nThis sketch only accepts HTTP requests, I may create a version that uses TLS (HTTPS) someday.\nThe sketch enables CORS, so if you access it from a web browser, you'll see two requests come in (rather than just one). The first one is the CORS request asking for supported options and the second request is the actual request.\nThere is one little weirdness about the code; in the initialization code that sets up the server, I used the following:\n\nI registered a request handlers for the server root (/) and for any other request (the onNotFound() method). Not because I needed to, but because I thought the code would look a little weird if it only registered a not found handler.\nAnyway, you can remove the root handler if you want, but at least this shows how to handle different requests that arrive at the server.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "M5Stack M5StickC-PLUS Garage Door Opener",
  "date":"Mon Feb 10 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1739232000,
  "url":"/posts/2025/m5stack-garage-opener/",
  "content":"In ESP32 HTTP Client Request with JSON Body I demonstrated how to call a remote API from an ESP32 device; in that example, the request body passed content in JSON format to the server. As I described in that post, I built that sample because I wanted to be able to build an ESP32 garage door opener and that was a stepping stone for me to this project.\nThis post is about that garage door opener.\nCode Available OnlineAll the code for this project is online at M5StackC-Plus Cloud Function Execution.\nTo build my garage door opener, I used the M5StickC PLUS ESP32-PICO Mini IoT Development Kit; it's a small ESP32 device with a small screen and a button on the face of the device. The form factor is perfect for my needs here.\n\nUsing the cloud function as a starting point, I built a sketch for the M5StickC-PLUS device that:\n\nValidates the configuration settings in the sketch (like Wi-Fi network, remote endpoint, etc.)\nConnects to my local Wi-Fi network\nDisplays &quot;Push Button&quot; with an arrow pointing to the button on the face of the device.\n\nThe device automatically powers down after 30 seconds of inactivity.\nIf the user pushes the M5 button on the device face before the 30 second shutdown limit, the sketch calls the remote function configured in the sketch and passes the data (also configured in the sketch) in the body of the request in JSON format. For my use case, the sketch calls my cloud function that triggers my garage door opener, passing in the required API key and other information required to perform the action.\nConfiguring the Sketch\nThe repository has more detailed instructions, but here's how you configure the sketch:\n\nThese settings and more are stored in an external configuration file and read by the sketch at compile time. With this approach, the user can modify the configuration without modifying the cloned repository; if I later make changes to the sketch, the user can quickly sync it and deploy it to devices.\nIf your particular cloud function requires one or more than two pieces of data send in the body, you can easily modify the configuration to accommodate as many or few properties as needed. You can even disable the JSON body by setting USE_PARAMS to false in the configuration file.\nStartup Time\nPowering up the device and it connecting to my home Wi-Fi network is typically the matter of seconds.  My home Wi-Fi network covers my driveway, so it's really simple for me to get in and out of my garage in seconds using the M5StickC-Plus and my sketch.\nShutdown Timer\nThe shutdown timer resets after every successful call to the remote host. In my case, I use the button to open the garage door when I'm in the car waiting to pull my car in the garage. Once I'm in the garage, I push it again to close it behind my car; the 30 second timer is enough time for this. Fortunately, the inactivity timeout value is easily modified before compiling and deploying the sketch.\nMultiple Cores\nI coded the sketch so it splits tasks across the ESP32's dual core architecture. The sketch's loop function executes on processor core 0 and the section of the code (the event loop) that calls the remote function executes on core 1.\nWith this architecture, while processor 1 is busy connecting to the remote host and processing the response, in the loop function on core 0 is unfettered by that activity I could add a screen animation to indicate that the device is busy without affecting performance of either task.\nAbout M5Stack Devices\nI'm a huge fan of M5Stack devices because they're generally:\n\nBuilt using high-powered ESP32 devices (my favorite)\nPackaged in a nice enclosure with a screen and one or more buttons\nPackaged with a rechargeable battery\n\nAnd they connect and charge using USB-C connectors (which should be the norm for any device today).\nI have a stack (no pun intended) of these devices and I'll post more about them over time.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Added Apps and Demos Page",
  "date":"Mon Feb 10 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1739232000,
  "url":"/posts/2025/apps-and-demos/",
  "content":"Over the years, I created several apps that solve a particular problem I had. The first was the Goodreads Page Adjuster and most recently the Cert2Arduino app. When I published a simple service to use with my ESP32 HTTPS Client Request with JSON Body, I decided to publish a demo site visitors could use to try out the service as they worked on their related Arduino or ESP32 sketch.\nThe site is John Wargo's Apps and Demos, and it looks like this:\n\nAs I create more public facing apps and demos, I'll update the site to reference them.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Coding Unihiker Programs Using PyCharm",
  "date":"Sun Feb 09 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1739145600,
  "url":"/posts/2025/unihiker-pycharm/",
  "content":"A while back, the folks at DF Robot sent me one of the new Unihiker M10 devices to play with. I had a specific use case in mind for the device, but it took me a while to get around to using it.\nThe getting started documentation is really good and I was able to quickly get Visual Studio Code configured to talk to the device. It wasn't long before I had some of my code running on the device. I'm a huge fan of Visual Studio Code, I use it all the time, especially when coding or writing posts on this site. For python development though, I prefer to use the PyCharm IDE from JetBrains. JetBrains offers a free community edition, but I've had a Professional license for many years - mostly because you need the Professional license to deploy code to a remote device using FTP (or one of its variants).\nPyCharm Professional License RequiredThe remote deployment capabilities of PyCharm demonstrated in this post require a Professional license for PyCharm. As far as I know, you can't do this in the Community Edition. I purchased a Professional license specifically for this capability as I used it repeatedly while programming and testing Raspberry Pi projects.\nCreating a PyCharm Project\nTo start coding for the Unihiker using PyCharm, start by creating a new project in PyCharm. When PyCharm loads, it prompts you to either open an existing project or create a new one, select the new project option as highlighted in the following figure:\n\nIn the New Project dialog that appears, select a folder for the new project. The project folder must already exist, but you can click the folder icon on the far right side of the dialog to select a folder or create a new one. Once you have a target folder selected, click the Create button to create the project.\n\nCreate a new python file in the new project, in the example below, I called the program unihiker_demo.py. In the Editor, paste in one of the sample programs or write your own.\n\nOnce you have a program coded, you're ready to deploy it.\nPyCharm Deployment Settings\nIn the PyCharm IDE, select the Tools menu, then Deployment and finally Configuration.... PyCharm will open the following dialog:\n\nClick the + in the upper left corner of the dialog to create a new deployment configuration.\n\nPyCharm, for some bizarre reason, assumes you're connecting to a web server to deploy server code. This makes no sense to me; you'd think they'd consider other options as well like deploying Python code to a Raspberry Pi or Unihiker device. 😄 Ignore the &quot;Please add a web server to configure&quot; since that doesn't matter here.\nPyCharm first prompts for you to select the deployment connection type; I chose SFTP since that made the most sense to me. You may be able to use FTP or one of the other options as well.\nIn the Create New Server dialog (again, we're not creating a server location here, so just ignore the nomenclature) enter a name for the new deployment. I chose Unihiker for my deployment configuration since that made the most sense to me.\n\nNext, PyCharm opens the configuration dialog for the new Deployment connection. The first thing you must do is configure an SSH configuration for the deployment. Click the ...* button highlighted in the figure.\n\nIn the SSH Configurations dialog that appears, click the + button to create a new connection.\n\nIn the dialog that appears, enter:\n\n10.1.2.3 for the Host IP address\nroot for the Username\ndfrobot for the Password\n\nSelect a location for storing the SSH configuration, I selected ~/ssh/config for my system. My Windows desktop is broken, so I'm not sure what this looks like on Windows.\nClick the Test Connection button to validate the settings. If it doesn't work, change the parameters until it does. 😄\nClick the OK button when you're all set the the SSH connection works.\n\nBack at the Deployment configuration, the SSH Configuration field should populate with the SSH configuration you just created (and validated).\nFor Root path use /root.  Again, ignore the stuff about the web server URL, you don't need one since we won't have one.\n\nOn the dialog's Mappings tab, set the Deployment path to /\n\nClick the dialog's OK button to save your changes.\nBack in the code editor, right-click on the python program you want to deploy to the Unihiker device. In the menu that appears, select Deployment then Upload to Unihiker as highlighted in the following figure.\nNote: PyCharm doesn't know anything about a connected Unihiker; Unihiker was just the name I chose for my deployment profile. Naming it that way makes it crystal clear what I'm deploying to, right?\n\nThe selected python program should deploy to the connected device. On the Unihiker device, when you press the Home button to open the app menu, select 2-Run Programs and pick the root/ folder and you should see your deployed python program in the menu as shown in the following figure.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Playing Around with Info Orbs",
  "date":"Fri Feb 07 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1738972800,
  "url":"/posts/2025/info-orbs/",
  "content":"A while back, I learned about this ESP32 project called Info Orbs; it's a simple project that pairs 5 1.8 inch circular displays with a simple stand and some pretty cool software. The kit seems to be designed as a first project for people interested in getting into Arduino; it requires a little bit of soldering and the entire software configuration and deployment process runs in Visual Studio Code. The assembly instructions are simple and easy to follow.\n\nIf you're looking for an excellent way to quickly build a very interesting project with a young learner, this one's pretty cool; especially since you can use it to teach soldering.\nDuring assemblyI realized I wanted to present the orbs differently. I built it out as designed, but I already decided I'm going to build a wooden enclosure for it and I've already ordered the parts I needed.\nSoldering Issues\nMy father taught me how to solder when I was about 10 years old (I'm now over 60) so I thought I would have no issues with the simple soldering tasks required to assemble this project. I was wrong. Not because the parts are hard to solder, but because I made mistakes while I soldered the parts.\nWhen I assembled all the parts and deployed the compiled sketch to the device, one of the orbs was blank and the one next to it had content overlapping on it. I hopped on the project's Discord and after a quick search I found the solution.\nThe project apparently uses the cs pin on the displays to select which display gets which content. When soldering the last display, I did two things wrong. I didn't make a solid solder connection on the Ground (gnd) pin and I also didn't seem to have enough solder on the cs pin.  The faulty ground pin connection caused the issue with the blank display. The poor connection on the cs pin caused the content from the penultimate (second to the last) and last display's content to all render on the second to last display. I touched up all the connections on the failed display and everything worked perfectly (as you can see from the image).\nI'll let you know when I get the extra sat of parts and start building my wooden enclosure. In the mean time, I'm 3D printing an enclosure for it right now.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "ESP32 HTTP Client Request with JSON Body",
  "date":"Mon Feb 03 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1738627200,
  "url":"/posts/2025/http-client-esp32-with-json-body/",
  "content":"A few weeks ago I published an article called ESP32 Connect Using HTTPS that demonstrated how to build an Arduino sketch for the ESP32 platform that connected to a remote server using TLS (HTTPS). I wrote that article because I wanted to learn how to connect to a REST API running on a server online and I knew that most (all) modern API servers required TLS.\nI started with a simple example that requested data using a simple URL with one or more parameters in the requests's query string. The target server parses the URL and returns a block of data.\nAs I wrote that post, and example code, I knew that what I really wanted was to able to call a remote REST API and pass data in the request body in JSON format.\nSample ProjectAll of the source code highlighted in this post is from a GitHub repository called ESP32 HTTPS Client Request with JSON Body.\nBackground\nMany years ago, I built a remote garage door opener using the Particle Platform. I eventually implemented a cloud function to abstract away some of the complexities of the process; the cloud function allowed me to securely hide the API key and device ID needed to interact with the Particle platform in the request body (instead of the server URL). The result is a cloud function I can trigger to open my garage door no matter where I am in the world.\nThis sample sketch described in this post came from me wanting to build an Arduino/ESP32 project that opens and closes my garage door on a button press.  I'll show you that project soon.\nRemote host\nFor this project, I built and published a cloud function that simulates the requirements for the sketch. It's a public service and it requires two parameters passed in the request body in JSON format. When it received the data, it parses it and:\n\nReturns 200 (HTTP OK) and a success string if both request parameters are populated.\nReturns 400 (Bad Request) if any of the required parameters are missing or empty.\n\nI'll publish an article soon that describes that service and shares the source code.\nThe Code\nThe first thing I needed was a way to represent the request body in JSON format. Assuming I needed to pass a couple of parameters to the server in a JSON Object like this:\n\nIn my code, I can represent it as a simple String variable like this:\n\nNote: The extra backslashes in the string are there because c doesn't allow you to include a double quote character inside strings.\nEscaping Quote Marks in c StringsTo use a double quote character in a JavaScript string, you must 'escape' it with a backslash. So, if I want to make a string with a double quote in it, I must precede the double quote with a single backslash:String myString = \"This is a string with a double quote \\\" in it\";Basically, the backslash character tells the compiler to ignore the character in the string that follows.\nTo make my code more flexible and to avoid having to deal with all those escaped quote marks, I decided to use a String array to store the keys and their associated values:\n\nThen, in the function that sends the HTTPS request, I can simply build the JSON string on the fly like this:\n\nThe sketch needs some libraries, external files, and a few variables to operate:\n\n\nThe following table describes most of those things.\n\n\n\nObject\nDescription\n\n\n\n\nWiFiClientSecure.h\nThe ESP32 library for secure communications over a Wi-Fi network.\n\n\nHTTPClient.h\nThe ESP32 library delivering HTTP/HTTPS client capabilities. Note the spelling, on non-ESP32 Arduino, the file is called HttpClient.h. Pay attention, they're different.\n\n\ncert.h\nThe downloaded Certificate Authority (CA) certificate for the target host server converted into an c constant called caCert.\n\n\nconfig.h\nSo you can execute the sketch on your hardware without modifying the source code, I moved Wi-Fi and parameter settings to an external file. This way, if I make changes to the original source, you can download it and run it cleanly without having to reapply your changes. See the project readme for instructions on how to use the config file.\n\n\nssid\nThe SSID for the local Wi-Fi network the device connects to. The code pulls the String value from the external configuration file and converts it to a char pointer required by the client.\n\n\npswd\nThe password for the local Wi-Fi network the device connects to. The code pulls the String value from the external configuration file and converts it to a char pointer required by the client.\n\n\ntargetHost\nThe remote server the sketch connects to. It hosts a public cloud function I created for this demo. Please don't connect to it too much, I'm paying for it.\n\n\nWiFiClientSecure\nCreates the client object that makes the request. Later, I'll assign the certificate to the client so it can make secure connections\n\n\nHTTPClient\nAdds capabilities to the client object that allows the sketch to send the body of the request. If you look at the simpler sample, it's able to do everything it needs without adding HTTPClient\n\n\nresponseCode\nAn integer variable used to store the HTTP result",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Amazon Prime Invoice Scam",
  "date":"Tue Jan 28 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1738108800,
  "url":"/posts/2025/amazon-prime-invoice-scam/",
  "content":"Received a scam/phishing email the other day that really surprised me. The message is so clearly a scam that I wonder why they even bothered to send it. Here's the email message:\n\nDefinitely a ScamThere's a lot of reasons why this is a scam, do not call the phone number in the email.\nThere's a lot of reasons why this is a scam:\n\nThat's not the Amazon logo at the top of the message. Everything about it is wrong.\nAmazon Prime doesn't cost $239 a year, it costs $139 a year.\nAmazon doesn't use the term Sales Order Number, only companies with phone or in-person sales teams do. Amazon would call it an Order Number.\nThere's a bunch of underlined content in the email, but none of them are links. Amazon is smart enough to not use underline in their email messages because most Internet Savvy people will assume they're links.\nThere's no links in the email message, not a single one. Any email from Amazon would have at least one pointing to the Amazon portal.\nThere's no link to the recipient's Amazon account, or, at a minimum, the specific order referenced in the email.\nThe phone number is underlined in blue, making you think it's a link when it's not.\n\nDeliberate Mistakes\nA while back, I read an analysis of scammer messages and why they deliberately put mistakes in them.  The purported reason is to keep intelligent people from responding to them and wasting the scammer's time. Like in this instance, the email doesn't have any links you can click, you must call the phone number to yell at them for your unexpected Amazon Prime order. That takes up a human's time on the phone to talk you into giving them your Amazon account password.\nInstead, they want people who don't know what the Amazon logo looks like to call them.\nI can't remember in which book I read about this, but here's a random reference to the topic: Why Scammers Make Spelling and Grammar “Mistakes”.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Phishing Email Elon Electronic Device",
  "date":"Sat Jan 25 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1737849600,
  "url":"/posts/2025/phishing-elon-oracle/",
  "content":"An interesting email showed up in my inbox this morning. Interesting because it appears to be from Oracle (and I work for Oracle) but there's a whole bunch of weirdness about the message. Take a look, here's the message:\n\nLike I said, there's a lot of weirdness in this one:\n\nThe message says its from elonElectronlcDevlce 9O%ElectrlcReduction which is simply nonsense. Notice how they replaced i's with l's everywhere in the Sender? Weird, right? They're trying to say &quot;Elon Electronic Device 90% Electric Reduction&quot;, but deliberately didn't for some reason.\nThe sent from address is oracle-acct_ww@oracle.com which is in a valid email format and may actually be a real Oracle email address (I'm not going to check).\nEven if Oracle did send the email, they didn't, they wouldn't be sending me an email about Elon Musk.\nThe Learn More link points to a myshopify.com address.\nAll of the images on the page as well as the footer links all relate to Google Analytics.\n\nDefinitely FraudulentThis message is definitely junk and I wouldn't click on any links in the message nor would I let the mail client download any images from the message.\nWhat makes me wonder is the oracle.com part of this. Is this a targeted email because the hackers, spammers, or phishermen know I work at Oracle?  Or is that just coincidence. I have no idea.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Certificate Conversion Utility in Gemini",
  "date":"Fri Jan 24 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1737763200,
  "url":"/posts/2025/cert-conversion-gemini/",
  "content":"I was playing around in Google last night checking to see if my post on Arduino ESP32 connections using HTTPS (Arduino ESP32 Connect Using HTTPS) was in the search results. It wasn't, but the Certificate to Arduino announcement (Automated Public Cert to Arduino Header Conversion) post did make it into Google Gemini.\nHere's the generative API results for a search on &quot;Convert Certificate Arduino&quot;:\n\nIt was fun to see how quickly that made it into generative AI.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Certificate to Arduino Command-line",
  "date":"Thu Jan 23 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1737676800,
  "url":"/posts/2025/certificate-to-arduino-command-line/",
  "content":"Before I created the web application described in Automated Public Cert to Arduino Header Conversion, I started with a simple node.js command-line utility. I like command-line tools and starting with the Node version made sense to me. I switched to the web app version once I realized that most people who needed to do the certificate conversion to Arduino wouldn't have node installed on their development systems.\nSo I stepped away from the incomplete command-line utility then built, deployed, and documented the web app version. Last night, I finished the command-line version and published it. Its called, hopefully not surprisingly, Cert2Arduino and you can find it on npm at Certificate to Arduino Header Converter.\nWhen you execute it, it prompts for the same information the web application does:\n\nThe path to the downloaded certificate file\nWhether you want to append a backslash (Arduino's line continuation character: \\) or not.\nThe variable name assigned in the Arduino header file generated from the certificate file.\n\n\nLike the web application, it saves the outputted file to a file using the variable name as the file name. The web app allows you to change it, but I didn't do that here.\nAnyway, for you node users like me, you now have a tool you can use to convert a downloaded certificate file into an Arduino header file to use in your Arduino sketches.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "JavaScript",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "ESP32 Connect Using HTTPS",
  "date":"Tue Jan 21 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1737504000,
  "url":"/posts/2025/https-client-esp32/",
  "content":"As I described in my previous post, I'm working on a project where I'm using an M5Stack device to interact with a Google Firebase Function I have running in the cloud. As I started planning my project's code, I realized that the SSL (HTTPS) requirement Firebase Functions forces on applications would be a problem for me.\nInitially, I panicked a bit thinking that using HTTPS connections on an Arduino compatible device would be painful. I knew I'd have to manage certificates in my sketch and I wasn't looking forward to embedding certificates in my code and troubleshooting connection issues. It turns out the process is not that bad, so I decided to build a sample project, publish to GitHub and describe it here.\nCode Available on GitHubYou'll find all of the code for this project at HTTPS Client ESP32 Example.\nThe Goal\nThe goal for this project/post is to demonstrate how to code an Arduino sketch that:\n\nConnects over Wi-Fi network to a server connection that requires HTTPS/TLS.\nWrites content returned from the server to the Serial Monitor in the Arduino IDE.\n\nAnything else you want to do is up to you, I'm just showing how to connect to a server using HTTPS and process the data that returns. I have plans for publishing a post that digs into how to pass parameters in the body of the request; stay tuned for that.\nStarting Point\nFirst of all, this project is for the ESP32 family of devices. This is important because regular everyday Arduino devices don't support the secure connection as far as I know. The libraries used to do this are in the ESP32 libraries for Arduino. I think there are corresponding libraries for espressif es2886 devices, but I've not researched them.\nTo build this example, I started with the Arduino BasicHTTPSClient sample sketch. For a variety of reasons, the sample sketch didn't work for me, so I had to go off on my own and write this.\nThe Public Service\nFor this project, I selected the JSON API exposed by Bacon Ipsum. I did this for a variety of reasons:\n\nI think Bacon Ipsum is a cool site and I use it regularly to generate meat-flavored content for documents, and other stuff, all the time.\nThe API the site exposes is free to use.\nThe API is very simple to use; perfect for this simple example.\n\nGetting the Certificate\nI will not provide a lot of details about using HTTPS over HTTP; I leave it up to you to have the background you need to understand this topic (sorry).\nTo use an HTTPS connection, the sketch must have access to the public version of the certificate the server uses to encrypt the content between the client and the server. The good news is this is really easy to get.\nNote: For the screenshots, I'm using Chrome, but any modern browser should work similarly.\nI opened my browser of choice (Chrome) and navigated to https://baconipsum.com/. On the page that appears, I clicked the security options icon that appears left of the URL in the interface (highlighted by the green arrow in the figure below).\n\nIn the window that pops up, I clicked the Connection is secure option highlighted in the image:\n\nIn the window that appears, I clicked the external link next to Certificate is valid highlighted in the image:\n\nA dialog appears that displays general information about the certificate.\n\nI clicked the Details tab in the dialog and the dialog content updates to show the hierarchical relationship between the server's certificate (baconipsum dot com) and the Certificate Authority Root certificate (ISRG Root X1). As I understand this, the site has a site-specific certificate, which is signed by the R11 certificate which is signed by the ISRG Root X1 certificate.\n\nI selected the ISRG Root X1 certificate in the dialog's Certificate Hierarchy section (as I did in the previous image), then clicked the Export... button.\n\nI saved the exported certificate to my Arduino project on my local system. When I opened the file in a text editor, I saw the following (with the three vertical dots indicating there's more to the file than what I'm showing here):\n\nConverting the Exported Certificate to Code\nTo convert the certificate file into code you can use in the sketch, I converted it into a character array as shown in the following example. I started by copying the exported certificate file to a file called caCert.h in the Arduino project and opened it in a text editor (yes, you can use the Arduino IDE to edit it).\nIn the editor, I followed these steps:\n\nAdded the const char* cert= \\ at the top of the file.\nAdded a double quote (&quot;) at the start of each line.\nAppended \\n&quot; to the end of each line in the file.\n\nNote: In the following example, I removed the bulk of the certificate content for readability; your file will NOT have the three vertical dots (I put them in there to show you that there is content missing).\nHere's an example of the converted content:\n\nOne of the tutorial posts I read suggested using the following format as well; each worked fine in my testing. The only difference is the addition of ",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Automated Public Cert to Arduino Header Conversion",
  "date":"Sun Jan 19 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1737331200,
  "url":"/posts/2025/public-cert-arduino/",
  "content":"I'm working on a project where I'm using an M5Stack device to interact with a Google Firebase Function I have running in the cloud. As I started planning my project's code, I realized that the SSL (HTTPS) requirement Firebase Functions forces on applications would be a problem for me.\nI started investigating different options for my project:\n\nGenerating a self-signed cert won't work because it's Google's public cert I need for secure communications to the cloud function.\nI could build a local proxy device, running on a Raspberry Pi Pico W  for example. That allows me to connect via HTTP to a REST API exposed by the device while the code behind it connects via secure HTTPS connection to the Functions backend. This would definitely work, but leaving a Raspberry Pi running just for this use case didn't make sense.\n\nI did some research and learned that ESP32 devices had access to sending HTTPS requests. The drawback of the process is that you needed the server's public cert embedded in your code to make this work. Looking at examples, this looked like it was a reasonable approach, so I started digging into the details.\nModifying the Public Cert for Arduino\nTo start, you must download a server's public key into a .pem or .crt file. I'm not going to show you how to do that here, just follow the instructions found online. Here's a good example: How to Download the SSL Certificate From a Website in Windows.\nThe download certificate is a text file with a specific format:\n\nThe file contains a header (-----BEGIN CERTIFICATE-----) and footer (-----END CERTIFICATE-----) that delimits the certificate code. Everything in between is the raw code of the public certificate.\nNote: That particular file is 184 lines long, so I used the three periods vertically  in the middle to indicate that part of the file was cut out of the example.\nTo use that certificate in an Arduino sketch,  you must first convert it into a format that the Arduino IDE understands. Specifically you must convert it to a file that:\n\nDefines a variable name for the certificate. You'll reference this name in the code that leverages the certificate. In the example code below, this is the const char* cert= code that creates a variable called cert for the certificate.\nAdds a continuation character (\\) at the end of every line (except the last one) telling the Arduino compiler that there are more lines in the current statement.\nQuotation marks (&quot;) at the beginning and end of each line (before the continuation character).\nA newline (\\n) at the end of each line before the ending quotation mark.\n\nHere's what the modified file looks like (with the same indicator showing that I dropped a bunch of lines from the output):\n\nMaking those changes to the certificate file isn't impossible, but at 184 lines for this particular example, it's pretty tedious work If you have to do this frequently for certificates for different sites. Since I don't like doing that type of tedious work, I decided to build a utility that handles the process for me (and you).\nAutomating the Conversion Process\nTo automate this conversion process, I published a simple web application that converts a public certificate into the source code needed to use the certificate in an Arduino sketch. The utility is called Cert2Arduino and it's hosted on Netlify.\n\nTo use the app:\n\nSpecify the variable name for the imported certificate code, the app uses cert by default\nBrowse and select the downloaded public cert.\nGenerate the Arduino code from the cert and save it to your local development system.\n\nThat's it, that's all there is to it with no manually editing 184 lines of certificate code.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "ESP32",
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)",
  
    "Web Development"
  
  ]
  },

  {
  "title": "Amazon Refundable Order Scam",
  "date":"Wed Jan 15 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1736985600,
  "url":"/posts/2025/amazon-refundable-project-phish/",
  "content":"I received an interesting text message the other day purporting to be a message from Amazon letting me know about a &quot;refundable order that needs to be processed.&quot; I could tell immediately that it was a scam or phishing attempt, so I thought I'd share what I saw.\nDon't click the linkThis message is definitely a scam or Phishing attempt.\nFirst of all, here's the content of the message I received:\n\n[Amazon]You have a refundable order that needs to be processed. Due to issued caused by the seller, no return is required. Please proceed with the refund request at your earliest convenience. If you have any questions, feel free to contact our customer service team.\n\nand here's a screenshot of the message I received:\n\nThere's a lot of things wrong about this message:\n\nThe use of [Amazon] at the start of the message. There's no reason Amazon would do that.\nThe lack of the space between the [Amazon] and the first letter of the remainder of the message. If Amazon actually sent the message, it would have been reviewed multiple times and that would have been corrected.\nThe URL in the message uses https://t.co which is a Twitter domain: &quot;Twitter uses the t.co domain as part of a service to protect users from harmful activity, to provide value for the developer ecosystem, and as a quality signal for surfacing relevant, interesting Tweets.&quot; Amazon doesn't use a Twitter (I refuse to call it X) domain for their url shortener; they have their own at amzn.to.\nThe message is a group chat. Amazon would never send a group chat message to any customer.\n\nWhen I tapped on the message details at the top of the text, my SMS application displays the list of phone numbers included in the group. Again, Amazon would never send a group chat message to a customer.\n\nIf you get this message, don't click on the link. It's either a scam or some sort of phishing attack.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Refactored Goodreads Page Adjuster App",
  "date":"Mon Jan 13 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1736812800,
  "url":"/posts/2025/refactored-goodreads-page-adjuster/",
  "content":"About two years ago, I published an article describing a web app I created that helps you Accurately Calculate Reading Progress in Goodreads. The app's simple and helps you calculate an accurate completion percentage taking into account those pages at the end of the book that you never read (notes, appendices, first chapters of the next book in the series, etc.).\nI opened the app the other day because Goodreads says the current book I'm reading, The Soul of America: The Battle for Our Better Angels, has 416 pages in it when there are only 272 of actual reading content.The disparity between reality and Goodreads is so great that I wanted a more accurate view of how far I made it through the book.\nAs I looked at the app, I realized it just didn't look very nice. When I wrote it, I just learned React and I wanted to learn how to use Bootstrap with it. The app works, but it just looked lame.\nA while back, I discovered MVP.css; it's a simple stylesheet that quickly makes any single page app look great (and supports multiple page apps too). I decided to give the app a facelift using MVP.css.\nThe app was old, so I had to upgrade it to React 19. Next, I stripped out all the Bootstrap stuff and converted it to MVP.css. Here's a screenshot of the results:\n\nIt looks much better and the code is a lot easier to read.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Web Development"
  
  ]
  },

  {
  "title": "Timezone Fix for the Eleventy Stats Plugin",
  "date":"Sat Jan 11 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1736640000,
  "url":"/posts/2025/timezone-fix-for-eleventy-stats/",
  "content":"In a short post yesterday, I mentioned that I noticed that my Eleventy Plugin Post Statistics wasn't working correctly. For this year's posts, the post count was short one post.\nI did some initial troubleshooting and noticed that the issue arose for any year where I published a post on January 1st (it didn't matter the year). The plugin treated any post published on that date as being published on December 31st of the previous year; the post wasn't missing from the stats, it simply was reported in the previous year's post count.\nThis morning I started working on the fix; I knew what the issue was, just not how to fix it cleanly.\nPreviously Encountered IssueI ran into this issue previously and wrote about it in Added Timestamp to Posts. \nIn an Eleventy site, you write the post date as a string representation of the date to the post's front matter; its as a date value, no timestamp. You can skip that property in the front matter and Eleventy will use the create date for the post file.\nWhen the plugin's JavaScript code reads the date string from the post, it converts it into a JavaScript Date object but represents the date in Coordinated Universal Time (utc). So, my post published in the US Eastern Time Zone (GMT-5), but in UTC the post date is 5 hours earlier (because UTC is -5 hours from US ET). In my timestamp post linked earlier, I fixed this problem by forcing the US ET time zone on the cloud system that builds the site. That worked for my timestamp issues, but didn't work for this plugin.\nValidating the Issue\nI figured out the issue by taking a look at how the plugin represented the date values. In my plugin project, I modified posts at the beginning and end of the date range so they both show publishing on January 1st. Then, there's a section in the plugin where it stores the first and last post dates to variables, so I modified the code to write those values to the console:\nNote: All the code in this post is in TypeScript.\n\nWhen I executed a site build, the console reported that both January 1 posts were viewed as December 31st (in their respective years), 5 hours earlier than I expected. That's why the plugin stored posts published on January 1st in the previous year, because 12:01 AM in US ET on January 1st is 5 hours earlier (late evenining) on December 31st.\nImplementing the Fix\nOK, with that confirmed, I knew what I had to do. I had to add the timezone offset to the date values and all would be well. JavaScript has a getTimezoneOffset() method I can use to query the local system for its number of minutes offset from UTC. My development system is in US ET, so the method returns 300 (5 hours times 60 minutes per hour = 300).\nJavaScript treats Date/Time objects as if they were in milliseconds, so to use this offset in my plugin, all I had to do was convert it to milliseconds. There are 60,000 milliseconds in a minute, so the conversion of time zone offset to milliseconds looks like this:\n\nWith that in hand, I added a little function that took the date string from the Post and converted it into a JavaScript Date object adjusted to the local time zone:\n\nThen, in the code where I grab the post date from the post, I converted it using:\n\nI ran into one other issue that broke when I implemented the fix; I don't know why and I didn't dig too deep into it. When the TypeScript compiler hit this code in my plugin:\n\nIt generated the following error message:\n\nThe left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.ts\n\nI code my site in Visual Studio Code, so since I know that code is good code, I could simply add a //@ts-ignore to the line above the code and the error would go away. I don't like hacks like that, I'd rather fix errors if I can rather than telling the compiler to ignore them.\nWhat I did instead was use the getTime() method on the Date object to do the subtraction in milliseconds directly:\n\nWith that in place, the error went away and the plugin's fixed.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Eleventy Post Stats Plugin Broken",
  "date":"Fri Jan 10 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1736553600,
  "url":"/posts/2025/eleventy-post-stats-plugin-broken/",
  "content":"When I started blogging here in 2025, I noticed an issue with my Eleventy Plugin Post Statistics plugin.  If you use the plugin and publish a post on January 1st, the plugin won't include that post in the statistics. Sigh.\nAnyways, I'm working on fixing this and should have an update published tomorrow.\nPostscript\nPlaying around with it a little more, I realized that the issue with the counts is that the plugin treats posts on January 1st as if they're in the previous year. Interesting.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Corrupt Arduino IDE Installation",
  "date":"Fri Jan 10 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1736553600,
  "url":"/posts/2025/corrupt-arduino-ide-installation/",
  "content":"I'm a big fan of M5Stack products, I have a collection of their devices here but I never seem to do much with them. In one of the periodic newsletters I receive, I noticed a cool project for an M5Stack Core Ink device I wanted to try out. The project is the Keychain Skimmer Scanner project that helps you locate Credit Card Skimmers.\nI quickly pulled out the right device and started working on getting the code compiled and deployed to the device. I immediately ran into a bunch of problems, and I really struggled to get it to work. I visited the Issues area of the code repository, and created an issue outlining my problem. It turns out that there were some minor issues with the code and instructions, but even after resolving them I still couldn't get the code to compile and the errors I got simply didn't make sense.\nIf you look at my issue at Code won't compile you can see the error messages I received from the compiler. In one of the examples, the compiler complained that a method referenced in the code did not exist. I took a look at that particular library's source and realized that the owner had refactored the code and moved some methods into a separate file or library.\nLooking at my local configuration, I realized that I had some older versions of the libraries on my system. I quickly uninstalled Arduino Studio and deleted the libraries folder, rebooted, installed everything again, and gave it another shot. Sigh, it didn't work.\nI put it aside for a while and started working last night on another M5Stack device project and encountered similar library incompatibilities. Realizing that I had bigger problems if none of my M5Stack projects would compile, I started digging into this in earnest.\nI uninstalled and deleted everything again, but then started looking for any other detritus left on the system. I run Windows on my primary development system (I have a macOS system as well, but I don't use it as much) and I found some additional files that remained after the uninstall.\nThe first set of files was in c:\\users\\john\\.arduinoIDE as shown in the following figure. Delete that folder.\n\nNext, I looked in the system's Application Data folder and found the following:\n\n\nThe easiest way to find the system's AppData folder is to open File Explorer, select the path input field, type %appdata% then press the Enter key. AppData is an environment variable that points to the system's roaming data folder.\n\nThere's two different Arduino IDE folders in that location: Arduino IDE and arduino-ide. Sigh. I'm not sure why there's two of them, but the arduino-ide folder contains settings, code cache, and other stuff as shown below.\n\nThis must have been the source of my issue. Once I whacked (deleted) all three folders and reinstalled every one of my existing issues went away.\nSomehow my system's configuration got corrupted and wouldn't install updated versions of the libraries already installed.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Eleventy Packages Page",
  "date":"Thu Jan 02 2025 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1735862400,
  "url":"/posts/2025/eleventy-packages-page/",
  "content":"When I migrated this site to Eleventy (11ty) Eleventy last year, one of the reasons I did it was because I wanted to have more control over how my site worked and what features it had.  The previous site ran on Joomla!, and I didn't have the PHP skills to tweak and tune the behavior of the site. Eleventy, being JavaScript/Node.js-based, allows me complete control over the site's capabilities and I love it.\nA while back, I started thinking about adding a list of all of my published npm packages. I didn't believe it was critical to list them on the site, but I wanted to figure out how. I created a Eleventy plugin project for this and worked on it for a while, but left it alone for a while. This week I rediscovered the project and started working on it again.\nnpm makes it easy to get a package list for a specific publisher (in my case johnwargo) through a public API. As I worked on the plugin, I realized that I didn't need a plugin for this, all I needed was a little bit of JavaScript code.\nWith that in mind, I scrapped the plugin project and added a file called packageList.js to this site's _data folder.  The code essentially fetches the package list using npm's REST API and returns the data object.\n\nI also published the code in a Ghist.\nNext, I created a page on the site that renders the package list in a two-column table:\n\nYou can see the resulting page here: Packages. Enjoy!\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Welcome to 2025",
  "date":"Tue Dec 31 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1735689600,
  "url":"/posts/2025/welcome-to-2025/",
  "content":"Its the first day of 2025 and I thought I'd start things off a little differently this year. This post is both a retrospective on last year's activities and a look into the future of this site (at least for this year).\nRetrospective\nLast year I wrote slightly less posts than the previous year (59 vs. 68). One of the reasons for so many articles in 2023 was that I migrated a lot of sites to Eleventy that year (from Joomla! and Wordpress) so I had a lot to write about.\nIn 2024:\n\nI wrote a lot more posts about spam and phishing emails and text messages I received.\nI wrote a lot more posts about Eleventy(11ty), including adding some new capabilities to existing utilities.\nI suspended my US Presidential campaign and decided not to run again.\nI spent a lot more time in my workshop than at my desk writing code, so that explains part of the deficit.\nI released a Path Backup (and Restore) utility for Windows.\nI built a documentation site using Docusaurus.\n\nWorkshop Projects\nHere's some of the projects I built last year:\nA benchtop power supply with a 3D-printed case.\n\nI made three Owl houses:\n\nA cherry napkin holder:\n\nA set of storage shelves for some jars full of nuts I had in my shop:\n\n\nA new storage cabinet for the shop\n\nA new stand, with amplifier and speakers, for Sparky, my remote control flame throwing pumpkin&quot;\n\n\nLooking Forward\nWhat does 2025 look like for me?\n\nI plan on doing even more woodworking in my shop; I'm honing my skills for retirement.\nI'm on track to eliminate the only debt I have (my mortgage) and get my kids moved out of the house.\nI may retire or start working part time (who knows)\nI plan on finishing this site's upgrade to Eleventy 3.  I figured it out and upgraded several sites, but upgrading this one is biting me in the ass.\nI bought a better 3D printer last year (a Bambu Labs X1C), so I plan on learning how to design my own projects for printing.\nI'd like to add a newsletter to the site so people can subscribe to updates\nRaymond Camden publishes periodic lists of links to things he's looking at, I may do that this year as well (that's the goal anyway).\n\nThat's all I have right now, see you soon\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Eleventy 3 Upgrade Fixed",
  "date":"Sun Dec 29 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1735516800,
  "url":"/posts/2024/eleventy-3-upgrade-fixed/",
  "content":"In Eleventy 3 Upgrade, I described a process I used to migrate several Eleventy sites from V2 to V3. As part of that process, I was able to skip some important upgrade/migration steps because my development and deployment environments run Node.js version 22. Specifically, even though Eleventy 3 expects all modules to use ESM, a feature in Node.js 22 allowed my sites to build and deploy successfully without it.\nEven though this worked, I didn't want to leave the sites in that state. Eleventy 3 uses ESM, and I didn't want to run into issues later due to me skipping that conversion step.\nAt first, I was intimidated by the process, but it turns out it's really easy to do. What hung me up was that I made an stupid developer (me) error while converting one of the site's imports. I wrote about my failure in Eleventy cannot be invoked without 'new'. Once I resolved that error, the rest of the process was easy.\nConverting to Module\nThe first step in the process is adding a type property to the site project's package.json file:\n\nHere's my example project's package.json file with the modification:\n\nWith that change in place, when you build the site, Eleventy will start complaining about module imports. You must fix them next.\nMigrating to Imports\nThe site originally used the JavaScript require() to load modules:\n\nAll I had to do was convert them, all requires used by the site, to this format:\n\nHere's the previous example converted:\n\nNote: Use the search capabilities in your code editor to find all references to requires( and replace them as shown in the example above. If you miss any, you'll find them during the Eleventy build process.\nDon't try to build the site yet, it still won't work.\nDefault Exports\nThe last step is to modify the exports of all of the packages loaded by your site. That means that you must migrate all versions of this code:\n\nto this:\n\nIf the exported function uses parameters like the following:\n\nYou must convert it to something like this:\n\nNote: the function in the example above is required, it's not an example for a generic function name.\nThat's it, that's all I did to complete the site's migration to ESM.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Eleventy 3 Upgrade",
  "date":"Sat Dec 28 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1735430400,
  "url":"/posts/2024/eleventy-3-upgrade/",
  "content":"I run quite a few sites on Eleventy; you can see the complete list on this site's Sites area. The Eleventy team released version 3.0 a while back and I finally got around to upgrading some of the sites. This post describes the process I used.\nEleventy provides some tooling to help with this process, specifically the Upgrade Helper, but I also found some other sites with articles explaining the upgrade process:\n\nMajor Version Upgrade Helper\neleventy-upgrade-help v3.0\nUpgrading to Eleventy v3\nUpgraded to Eleventy 3.0 (Beta)\n\nFor this post, I upgraded my 2024 US Presidential Candidacy site: Wargo 2024 which I'll pull down as soon as the domain expires and I don't expect to run again. I'll keep the source code available online, you can find it on GitHub at wargo-2024-11ty.\nSetting The Package Type\nIn Upgrading to Eleventy v3, the author instructs you to change your Eleventy project's package type to module, but I found that I didn't need to do that because my development system runs Node.js 22 which makes this change unnecessary.\nNot changing this caused me some problems later, refer to the Netlify Hosting Issue section below for details.\nIf you're not running Node.js 22, you must manually convert all of the packages used by your site to use ESM Modules. Instructions for doing so are in the Upgrade Helper output below and the link at the beginning of this section.\nEleventy Upgrade &amp; Tools Install\nThe Eleventy team published a helper plugin that helps you identify problems with your site during the upgrade process. To perform the initial upgrade, open a terminal window in your Eleventy project folder and execute the following commands:\n\nThis replaces the Eleventy 2.x package with the 3.x package and installs the helper.\nBefore executing those commands, my project's package.json file looked like this:\n\nAfter the changes:\n\nNote: I changed the minor version of the package manually to 0.1.0.\nWith those changes in place, you must modify the project's eleventy.config.js file to load the helper plugin:\n\nNote: For Upgrade Helper to work correctly, it must be the last plugin loaded.\nHere's a complete example of the modified file from the project (with shortcodes and some other stuff removed):\n\nAt this point, the site's been upgraded to Eleventy 3.x. With that in place, you're ready to test the upgraded site; this is where the fun starts.\nTesting The Upgrade\nTo test the upgraded site, execute the Eleventy build process:\n\nThe Upgrade Helper will analyze your site and display the results of multiple tests it performed against the site. You'll also see the normal build process output as shown in the following image:\n\nHere's the complete output from the process:\n\nAs you can see from the results, most of the tests passed with only a single recommended change; I'll explain that change in the next section.\nIf the Upgrade Helper identifies any errors, you must fix those errors before continuing.\nUpgrade HellWhen I first attempted to upgrade this site, I tried to follow the instructions regarding converting all of the site's modules to ESM. This was a nightmare because every time I fixed one issue, another one popped up. After trying for a couple of hours to squash all of the errors, I finally gave up and started the upgrade process on a smaller, less complicated site. It's there that I realized I didn't need to migrate everything to ESM, it all just worked on Node.js 22.\nIf you're using a version of Node.js older than 22, the Upgrade Helper will likely report errors for every non-ESM module used by the site. It reports one at a time, so you must fix an error before running the build again to find the next one.\nGenerator Tag\nIn a fit of self-promotion (that I don't disagree with), the Upgrade Helper recommends adding a generator meta tag to the site's pages:\n\nNote: I removed the list of affected pages from the message to make reading it easier.\nThis was easily done before Eleventy 3 (I'll write about this in my next post), but I had to take a different approach for this site.\nThe eleventyConfig object exposed by Eleventy doesn't contain a version property; I'm not sure why, but it should. So, in order to get the generator version number, the site has to read and parse the @11ty/eleventy package's package.json file to obtain the value.\nI created a file in the project's _data folder called eleventyinfo.js that looks like this:\n\nNote: The code is a hack that I'm not proud of, but it works. What it does is reads the contents of the @11ty/eleventy package and converts it to a JSON object. With that in place, it's super easy to pull out the package name and version from the object.\nDuring the build process, Eleventy executes the file and makes the data result available via the eleventyinfo object. Then, to use it in the site, you simply reference it in HTML using:\n\nNote: I use Liquid templating language in my site, so that's a liquid example.\nSo, in the the head section for each page template, I added the following code:\n\nHere's a c",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Displaying Eleventy Version On A Page",
  "date":"Sat Dec 28 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1735430400,
  "url":"/posts/2024/displaying-eleventy-version/",
  "content":"Update: Soon after I posted a link to this article on Mastodon, the Eleventy team responded with\n\n@johnwargo you needn’t parse your package.json for a meta generator element: you can use Eleventy v3.1.6 directly, it’s supplied for free by Eleventy! Docs: https://11ty.dev/docs/data-eleventy-supplied/#use-with-meta-namegenerator\n\nSo it turns out you don't need any of the stuff that follows. :-)\n\nA while back, I added the Eleventy build details to the footer of this site; here's what it looks like today:\n\nDoing this was pretty easy. First, I added a data file to the site, creating a file called eleventyinfo.js in the site's _data folder (_data/eleventyinfo.js) with the following code:\n\nThe code loads the Eleventy package.json file as an object using require(), then returns an object with a string representing the package name and package version.\nWith that in place, any page in the site can display the generatorStr value using eleventyinfo.generatorStr. So, in the site's footer is the code that displays the value shown in the image above.\n\nThis worked very well for a long time, but when I started playing around with Eleventy 3, the code broke. On an Eleventy 3.x site, building the site with that code in place generates the following error:\n\nA quick online search took me to the following Google AI generated message:\n\nThe error message &quot;Package subpath './package.json' is not defined by 'exports'&quot; in Eleventy means that you're trying to import a file directly from your project's package.json file, but your package.json file is configured to only export specific modules through the &quot;exports&quot; field, and the root directory (where package.json resides) is not explicitly included in those exports\n\nI'm not an expert, but I generally understand what the error is telling me and since I won't be able to modify the source package file, I had to look for other solutions.\nFix for Eleventy 3\nI didn't spend a lot of time researching the best solution, I just leveraged my existing JavaScript capabilities and came up with this, changing the name of the file from eleventyinfo.js to eleventyinfo.mjs:\n\nInstead of loading the package through require, the code just reads the package.json file directly from the Eleventy package folder ./node_modules/@11ty/eleventy/package.json then uses JSON.parse method to convert it to a JavaScript object.\nThat's it, it works great. Its a hack and I'm not that proud of it, but it works.\nAlternative Option\nMy existing approach return a string, and that supports my use case very well. If I needed the package properties as separate values, I could use:\n\nThen, in the site content, reference the individual properties like this:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Upgrading Old Flutter Apps",
  "date":"Fri Dec 27 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1735344000,
  "url":"/posts/2024/upgrading-flutter-projects/",
  "content":"I recently purchased a Google Pixel 9 phone and migrated all of my stuff to it. The transfer process is very thorough and gets all of my app store apps plus existing data. Unfortunately, Google's migration process doesn't migrate applications I deployed to the device via side-loading (installing them directly on the device using Android Studio). These are Flutter apps I wrote for myself and I only update them when I get a new device. This post explains my process for upgrading the apps for new phones.\nDo Regular UpdatesWhen you make regular updates to a mobile app, it's easier to keep up with all of the changes the device platform makes to APIs and so on. When you only update them when you get a new phone like I do, the process of getting the app to work on a new phone is quite the nightmare.\nBackground\nI've never been a full time mobile developer; I've had a lot of roles related to mobile development and wrote a bunch of books on the topic, but I've never had a job writing mobile apps. I've written a few for myself and I published a few to the Google Play and Apple App stores, but I don't regularly maintain them. When this means then is that when I try to build and deploy one of my Flutter apps for Android, I have to work my way through all of the changes brought on by:\n\nChanges to the Android operating system (this is usually permission changes that break APIs)\nChanges to Android APIs\nChanges to the Flutter SDK\nChanges to third-party Dart or Flutter packages\n\nThe process could be simple or it could be a nightmare, it just depends on how long it's been since your last app update and how many things changed on the platform and associated dependencies since then.\nBrute Force Update\nWhen upgrading a Flutter app for a recent Android release. if you're lucky, you can:\n\nLoad an old Flutter app in Android Studio.\nConnect your new phone to the system using a USB cable\nBuild and deploy the app to the new phone with no changes.\n\nThat's happened to me a couple of times, but that's not the norm.\nThere's always something that's not compatible anymore like a deprecated API or a Dart package that isn't maintained. What you have to do this case is work step by step through every error message you get until you finally get the app built and deployed to the connected device. In my experience this process could take hours or days (sadly).\nDependency Updates\nThere's a couple of steps to pay attention to as you do this, building the app between each step:\n\nEnsure Android Studio and all associated SDKs and device emulators are up to date. Start the whole process upgrading the entire Android development toolchain.\nExecute flutter pub upgrade in the project to deploy the latest version of all of the project's dependent packages.\nExecute flutter pub outdated in the project to identify packages that can be upgraded.\n\nThat should help you get through many of the issues with the app, but there's no guarantee.\nWarnings and Errors\nDuring this process, Android Studio will identify other problems with the application code. In many cases, Android Studio has enough smarts to recognize the error and offer a solution. Using the following image as an example, Android Studio underlines the problem code in yellow (warning) or red (error). Hovering the mouse over the underlined code opens a window that displays the error.\n\nIn this case, Android Studio doesn't offer a fix (which is too bad) so note that you can make the warning go away by replacing the print statement with debugPrint.\nThe following image shows a code error and Android Studio knows enough to recommend a fix:\n\nThe easiest way to address all of the issues like this in your code is to use the Dart Analysis tool shown below:\n\nIt lists all of the errors in the project and, when you double-click on an item in the list, the related file opens in the editor with the offending line of code highlighted. Work your way through each of the items in the list until there's no more changes you can make. In the example, these are items I don't have an immediate fix for; the app runs anyway so I'm not worried about them.\nTarget Project Errors\nInside a Flutter project for Android is a complete Android application project. The Flutter developer toolchain generates the app and applies specific settings in the app. Often when you're upgrading, you'll find incompatibilities in the underlying Android app and must follow recommendations for fixing those errors.\nAn upgraded Flutter app often requires changes to an Android app's build.gradle or AndroidManifest.xml file. This is where I get in the most trouble since I'm just not an experienced native Android developer. I can muddle my way though changes to both files if I have the right instructions but I generally don't know what I'm doing.\nFlutter BenefitThe cool thing about Flutter is that it isolates you from having to work directly in an Android or iOS project, but there are times when you can't avoid it.\nUnfortunately, I don't have an example to show y",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Flutter",
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Audi Q7 Drive System Failure",
  "date":"Wed Dec 25 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1735171200,
  "url":"/posts/2024/audi-q7-drive-system-failure/",
  "content":"I am an Audi driver, and have been for many years now. Until recently anyway. I was even making plans to trade in my current vehicle, a 2018 Audi Q7, for an Audi SQ5. However, while driving to Asheville NC to help with Helene cleanup, I experienced a nightmare *Drive System Failure and haven't had access to my car in over three months. This post describes my nightmare and the apparent Audi design flaw that ruined my vehicle and therefore dramatically reduced the value of the car.\nLong story short: It appears that the 3.0L engine in the Audi Q7 has a serious design flaw that causes it to begin burning oil (increased frequency of adding a quart of oil to the engine) that eventually results in a catastrophic Drive System Failure in model years 2017 to 2019.\nThe Incident\nWhile driving to Asheville with a car full of camping gear, a chainsaw, chainsaw tools, and other implements of destruction, I rounded a corner on the highway and my car loudly announced that the car experienced a Drive System Failure. I immediately pulled the car over and started to assess the situation. As soon as stopped, the engine started shaking violently in the bonnet. I quickly turned off the engine and never drove it again (this was three months ago).\nI called the leader of the church group we were working with in Asheville and he pulled up a few minutes later and took my wife and all of our camping gear to the campsite while I dealt with getting the car towed.\nGetting a Tow\nI immediately called AAA and arranged a tow truck to pick me up and take the car to the Audi dealership in Asheville for assessment and, hopefully, repair.\nAfter waiting about an hour for the tow truck, I started looking in the AAA app to see where my tow truck was only to find out that they sent the tow truck to Charlotte even though I clearly told them I was about 20 miles east of Asheville. Sigh.\nI called AAA back and explained where I was, and waited for the tow truck. After about another hour, I started checking status of the tow only to find that AAA sent the tow truck to South Carolina. As I said, I was parked on a highway about 20 miles from Asheville, nowhere near South Carolina. Well, that's not entirely true, but I was certainly closer to Asheville than I was to South Carolina.\nI called AAA back, the third time now, and successfully convinced them where I was. Less than a half an hour later, a tow truck finally showed up and flatbedded my car to the Asheville Audi dealership, dropping me off at the campground on the way.\nStaying in Asheville\nSince the car was in Asheville, I had to find a hotel room so I could be at the dealership Monday morning. The church group took my wife home and dropped me off in Asheville.\nAsheville was a mess, but at least I found a hotel with Potable water. Restaurants were open, but had very limited menus and only beer, wine, and canned sodas.\nAudi Asheville (Horrible Experience)\nWhen I called the dealership to make sure they were open (due to the hurricane) before towing the car to them, they explained to me that I needed an appointment for them to work on the car. I dutifully made one and went on with my business.\nThe dealership called me Saturday afternoon and let me know that they hadn't looked at the car yet, but they'd look at it first thing Monday morning.\nMonday morning, I took an Uber to the dealership to see how my car was doing. The service agent told me that they wouldn't look at my car until after they worked on all of the &quot;waiters&quot;.  I explained that the person I spoke with Friday didn't tell me I needed a &quot;waiter&quot; appointment, I also explained that my car was there before all of the other waiters. Eventually they looked at the car, and informed me I had two broken valves in a single cylinder and I needed a $30,000US replacement engine. Crikey!\nRather than continue to work with these idiots (and either stay in Asheville or drive home and back when they finally fix it), I decided to have the car towed to my local Audi dealership so they can fix it.\nExtended Warranty\nFortunately for me, I purchased the Platinum extended warranty for my vehicle which should cover the complete cost of the repair.\nWrong!\nSince the current value of the vehicle at the time of the breakdown was approximately $20,000US, that was the maximum the warranty company, in this case Audi (I purchased an Audi extended warranty), would give me to fix this.\nLimited WarrantyWhen you purchase an Extended Warranty from Audi, even the Platinum one, the maximum they'll pay for a repair is the current value of the vehicle and the time of the breakdown.\nSo apparently nobody repairs catastrophic engine failures anymore. When this kind of failure happens, they sell you a new engine and move on.\nIn this case:\n\nMy engine was broken\nNobody wants to fix it\nThe Warranty Company (Audi) won't pay enough to actually fix the car.\nIf I don't replace the engine, the value of the vehicle drops to about $4,000US. This is essentially selling it for part",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Automobiles"
  
  ]
  },

  {
  "title": "Parkit Scam",
  "date":"Sun Dec 22 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1734912000,
  "url":"/posts/2024/parkit-scam/",
  "content":"I received an interesting phishing/scam text message this morning. It seemed to come from a Charlotte Parking company notifying me of an unpaid parking invoice in the amount of $4.35 but there were a lot of things about the message that made me realize it was a scam.\nHere's a screenshot of the message:\n\nThere's a few things that make it clear its a scam pretty quickly:\n\nThe text message came from a Montreal Canada area code. It's possible that the City of Charlotte would use a Canadian company to manage their parking fees, but not likely.\nThe supposed late fee value is not formatted properly: 35$ instead of $35\nThe &quot;to avoid disconnection&quot; text in the message doesn't make any sense. How does paying a parking fee protect you from &quot;disconnection&quot;?\nThe message content is an image rather than text. It looks like its text, but it's definitely an image. For that reason, it looks different than any text message I've ever received. Anyone who wanted to send me a text message with a link to pay a parking fine would send it so I could tap on a link in the message to access the payment site.\nThe 'link' in the message is supposed to be for the City of Charlotte parking, but it's a parkit-nc dot com address (North Carolina instead of Charlotte). Still suspicious.\n\nAnyway, at this point I'm certain that it's a scam so I typed in the link address in my mobile device's browser. Chrome quickly blocked access and warned me about the site:\n\nIt's crystal clear at this point that someone's trying to harm me or steal from me.\nA Little More Research\nJust to make double certain, I started searching for &quot;Parkit&quot; as a parking solution in Charlotte. It turns out that the city of Charlotte does have a parking service called Parkit, but the site URL is http://charlottenc.gov/Transportation/Programs/Pages/ParkIT.aspx. This is a city service, so it wouldn't have a -nc in its site URL.\n\nTargeted Message\nI do live in Charlotte and own several cars so this is clearly an example of a phishing attempt specifically targeted at me or at least Charlotte residents.\nWhen I first received the message, my firth thought was &quot;OK, which one of my kids didn't pay for parking?&quot;. If the message was a text-based text message, I would have tapped the link to see which car it was so I could send the bill to the offending child.\nLuckily for me, as I've already shown, the browser would have blocked access to the site and saved me.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Shop Store Delivering Package to the Wrong Address",
  "date":"Thu Dec 12 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1734048000,
  "url":"/posts/2024/shop-store-delivery-wrong-address/",
  "content":"Many online stores today use Shopify and the Shop app to manage payments, shipping and so on. I like the convenience of this approach, but there are a couple of issues I uncovered with it over the years.\nDefault Shipping Address\nBy default, Shop uses the previously used shipping address for the next purchase. I discovered this when I tried to send a package to myself after sending some excellent toffee (from Bell Stone Toffee) to a work colleague. When I tracked delivery of the package, I realized that Shop used my colleague's address instead of my primary address. This makes no sense to me.\nBy default, Shop uses the previously used shipping address for the next purchase.\nBecause of this, my package went to her out in Seattle instead of to my house here in North Carolina. I sent her the postage required for her to send the package back to me then started looking for how to fix this issue.\nIt turns out that Shop allows you to set the default address for your account. Once I did that, Shop uses my default address unless I tell it specifically to use a different one. To change the default address, login to the Shop app, access your account settings, and open your primary address for editing. Once there, you can make a selection on the form to make this your default shipping address.\n\nOverriding Store Purchase Options\nAnother really annoying issue I discoverd with the Shop app is that it overrides the default purchase and shipping options for sites when active. I was looking at CNC Routers from Inventables and noticed that they supported a specific payment method I wanted to use for my purchase.\nThe site also used Shop and I was already logged into the Shop app when I visited the site. Because of that, the only purchase option I had was to use Shop; it overrode the purchasing capabilities of the hosting site and kept me from purchasing the product the way I wanted to.\nThis issue is easy to fix though, all you have to do is:\n\nOpen a new browser window.\nNavigate to the Shop App.\nClick on the account icon in the upper-right corner of the page.\nSelect Sign Out as highlighted in the following figure.\n\n\nWhen you switch back the product site and access your shopping cart, the site's default purchasing options should be available to you again.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "American Express Contact Details Scam",
  "date":"Mon Nov 25 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1732579200,
  "url":"/posts/2024/spam-amex-contact-details/",
  "content":"I received an interesting email today that seemed to be from American Express indicating that someone (most likely a hacker) updated the phone number associated with my account. The email subject said: &quot;Request To Update Your Contact Details Was Successful.&quot; and I almost panicked and clicked the link before I gave this careful thought.\nThe email message discussed in this post is NOT a valid email from American Express. It's a phishing email designed to capture your American Express account credentials when you click the primary link in the email. Do not click any links in the email and do not let Outlook load images for the email.\nFirst of all, when you look at the image, you'll see that Outlook blocked downloading images. I am an American Express customer, but outlook knows to trust email messages from them and automatically download images. The fact that images didn't download automatically means this wasn't a message from American Express, or, American Express changed the email user and/or domain for messages they send to me\n\nAbout the Email Address\nTaking a quick look at the email, I realized that it wasn't that American Express made changes to their system, it was because this message didn't come from American Express. Instead, take a look at the source email:\n\nNotice how they populated the email address with things you'd expect from a business email:\n\nno_reply\namericanexpress_com\namex\nwelcome\n\nAlthough I don't know why American Express would use welcome in an email to me about a profile change.\nAll of that text is designed to make you believe this is from American Express. It's not.\nAbout the Email Domain\nThis is the source domain for the email:\n\nDefinitely not American Express.\nWhen you check the registration for the develtio.dev domain, you'll see the following:\n\nThis tells you that it's an individual domain registration, not for a corporation.\nMore Clues\nI love how they knew that the mail client (outlook in this case) would block images so they added a message to get you to download them.\n\nPlease select &quot;Show blocked content and enable links&quot; to access secure message.\n\nThey even made the text look like a link even though you can't click on it. I'm not sure why.\nEven if you don't click any of the links in the email, downloading images allows them to at least know that the email address they sent the message to is valid and that you opened the email.\nFinally, looking at the link they want you to click:\n\nNote: Yes, I replaced the email domain in my email address - that's not a valid domain.\nI'm not sure what it does and I'm not going to click on it (neither should you) but this is clearly NOT an American Express corporate web site. I assume it will open a page that looks like an American Express login page.\nNormally I'd fire up a Virtual computer, install an operating system then open the link in that environment but the last couple of times I tried that the domain was blocked by the time I did so. Lets see what happens. Yep, here it is, a bogus login page:\n\nNotice the URL of the target site:\n\nDefinitely not an American Express site. Stay away.\nConclusion\nHopefully I was able to successfully convince you that the email message I shared here is a phishing attempt and you should delete the message as soon as you get it.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Google Identity Confirmation Failure",
  "date":"Sun Nov 24 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1732492800,
  "url":"/posts/2024/google-identity-confirmation-failure/",
  "content":"Google recently started asking for ID verification for Play Store developers. The time came for me to submit mine and I dutifully submitted both a scan of my passport as well as a scan of my driver's license (both sides). Google, of course, repeatedly failed the verification process without telling me anything about what was wrong with my submission.\nAfter failing a couple of times, I finally responded to one of the emails I received on this topic asking what the issue was. Only then did I learn that their issue was that I'd uploaded a black and white scan of my Driver's License.\n\nI don't know why I scanned it in black and white, but I did and that's why they wouldn't accept it.\nHow silly. They're telling me they wanted proof of my address and the ID does that, who cares if it's in black and white?\nNow, of course I could have read the instructions but even those don't help. The instructions say that you must:\n\nAccurately provide your developer account information, including the following details:\n\nLegal name and address\nD-U-N-S number, if registering as an organization\nContact email address and phone number\nDeveloper email address and phone number shown on Google Play where applicable\nPayment methods where applicable\nGoogle payment profile linked to your developer account\n\n\n\nIt doesn't mention anything about needing to upload a copy of your driver license nor does it say that the uploaded image must be in color.\nNothing like wasting my time.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Scammers Getting Slightly Smarter",
  "date":"Wed Nov 20 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1732147200,
  "url":"/posts/2024/scammers-slightly-smarter/",
  "content":"In Postal Scam Urtye dot com, I pointed out a lot of different ways you can easily tell when a text message you receive is crap. I received a lot more of those types of text messages lately and it's fun to watch them evolve.\nHere's a screen shot of one I received the other day:\n\nA couple of things are different. Most importantly the phone number is a US Phone number (Michigan), which at least makes some sense. Most of these I get are International phone numbers which, of course, the US Postal Service would NEVER use to send me a text message.\nInternational Phone Number?The US Postal Service (USPS) won't use an international phone number to send text notifications to US customers. It simply makes no sense. So, if a text message you receive supposedly from USPS and the sender's phone number begins with a plus sign and a two digit country code, then it is most likely junk/phishing/scam. Since the US created the telephone system text messaging is based on, our country code is +1, anything else is not a US phone number.\nHere's the content of the message so people can easily search on it:\n\nUSPS Notification: Your package could not be delivered due to incomplete address information. Please correct your address within the next 48 hours at this link: &lt;&lt; Link &gt;&gt; to avoid it being returned. We will redeliver within 24 hours once updated. Have a fantastic day full of peace and success, from the USPS team!\n\nMy most favorite part of this scam message is the &quot;Have a fantastic day full of peace and success, from the USPS team!&quot; Right, like the US Postal Service is going to wish me peace and success. ROFL.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Validating Links On This Site",
  "date":"Fri Nov 15 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1731715200,
  "url":"/posts/2024/validating-links/",
  "content":"When I migrated this site from Joomla! to Eleventy, one of the things I didn't spend much time on was validating the links in the site (both internal and external links). I recently decided to spend some time to check all of the links in the site and ended up spending time building a utility that automated the process for me.\nMy Requirements\nFor this solution, what I looked for was a utility (I didn't care of it ran in the web or via a command-line locally) that took the site's root URL and recursively looped through all of the links and generated a report I could use to manually fix the links and, in some cases, manually validate the the link was truly broken.\nW3C Link Checker\nI did a quick Internet search on &quot;link checker&quot; and one of the top results (not the top one though) was the World Wide Web Consortium's (W3C) Link Checker utility.\nWith this site, you enter the site URL and select some configuration options and off it goes to validate all of the links. The app is really slow, but it delivers a lot of useful information about the different links and associated errors or issues with reaching them.\nHere's a small example from the results:\n\nIt shows a couple of links that failed because the server blocked robots. That's helpful, it lets me know I need to manually validate those links. It also shows some redirect issues that indicate changes I had to make to my site's code to avoid the delay caused by a redirect.\nThe solution I ended up with for link checking (described below) doesn't provide some of this information, so I expect I'll continue to use this checker for the unique data it provides.\nAn issue I have with the W3C link checker is that I can't save the results to a file. I looked repeatedly for a Export button, but couldn't find one. So I can only work on these errors with the results page open. I could, I guess, submit a PR that implemented download, perhaps I'll do that.\n@johnwargo/link-checker\nAs I wrote in Yet Another Link Checker Utility, I recently published a node.js-based command-line utility that uses the linkinator package to validate a site's links. This utility does a rudimentary job at scanning links. I can use it to quickly find broken links in the site; for example: those caused by typos and errant spaces.\nThe link checker also generates failures for a variety of reasons, some of which are not valid. As I mentioned in the previous post, sites that perform a human check before letting you in report as broken links. I could probably set some HTTP headers to let those checks pass, perhaps I'll do that in the future.\nLinkinator delivers a lot more information than I display in the report, so it has the ability to tell me a lot more about why a particular link failed. I just didn't spend a lot of time pulling that data from the results. In a while I'll likely update it to provide more useful information in the report. Stay tuned on that one.\nConclusion\nI found that I received tremendous benefit from both utilities.\nThe W3C Link Checker is slow but delivers more information and more accurate information. I use this to find link formatting issues that my @johnwargo/link-checker doesn't.\nMy @johnwargo/link-checker utility is fast and allows me to quickly find typos in links throughout the site, especially internal links I entered by hand.\nThe overall result is this site now has much higher quality links - which is why I started this process.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Web Development"
  
  ]
  },

  {
  "title": "Suspended Presidential Campaign",
  "date":"Fri Nov 15 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1731715200,
  "url":"/posts/2024/suspended-presidential-campaign/",
  "content":"A few weeks before the 2024 election, I suspended my campaign for president. I didn't want to keep votes from the candidate I wanted to win. I'm getting ready to delete the web site for my campaign but I thought I'd share with you links to the campaign store in case you want to pick up any Wargo 2024 branded items as a form of protest against our political system.\nHere's links to the two stores:\n\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Added Automated Mode to Link Checker",
  "date":"Fri Nov 15 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1731715200,
  "url":"/posts/2024/link-checker-automated-mode/",
  "content":"After publishing my link checker utility, I realized I wanted the ability to write the utility's settings in a project folder so I could quickly scan links for that project.\nI just published an update that enables Auto mode in the utility. With Auto mode, you:\nRun the checklinks command the -s flag: checklinks -s. This causes the utility to prompt you for configuration settings as usual, but then writes all of your choices to a file called link-checker-config.json in the current folder. Once it completes writing the settings to the file, the utility exits.\nThe output looks like this:\n\nNext, run the checklinks command with the -a flag: checklinks -a\n\nI hope you like it.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Node.js"
  
  ]
  },

  {
  "title": "Yet Another Link Checker Utility",
  "date":"Thu Nov 14 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1731628800,
  "url":"/posts/2024/link-checker-utility/",
  "content":"I played around this week with validating all of the links on this site and trying some tools. As part of my research I found an article called Using Node.js to Check for Broken Links that showed how to use the npm package linkinator to build a command-line tool for validating links on a URI.\nI quickly built a command-line tool using information from the article and the linkinator package's documentation. Before long I had a full fledged link checker that met my specific needs. I called my link checker link-checker but since there is already a package with that name on npm, I had to add my npm username to the package name: @johnwargo/link-checker.\nValidating Links On This SiteIn my next post, I spend more time explaining how I used the two utilities to fix a lot of the links on this site.\nThe utility doesn't require any command-line parameters (which I like because I always forget them, especially for my own command-line tools) but does support a couple of them. What I like best of this utility is that it allows me to save the results to a file, enabling me to open it later in an editor and double-check the links the utility reported as broken.\nThe reason for this is that many sites (like the Adafruit Forums) have a human checker in front of access, so for that site, and sites like it, the link checker fails on those URLs. Something like the W3C Link Checker doesn't seem to have that problem.\nTo use the utility, you have several options, but I generally install tools like this as Global packages so I can execute them from anywhere. With the utility installed, I simply open a terminal window and execute the following command:\n\nThe utility then prompts you for all of its operational parameters, then starts scanning:\n\nFor my Random Errors site, the report, in markdown format, looks like this:\n\nThe report looks like this in a markdown editor:\n\nGive it a try and let me know if you like it.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Web Development"
  
  ]
  },

  {
  "title": "Conditional Prompting Using Prompts",
  "date":"Sat Nov 09 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1731196800,
  "url":"/posts/2024/conditional-prompting-using-prompts/",
  "content":"Over the years, I published a variety of Node.js modules and CLIs; the CLIs because I wanted to automate some operation I needed to make easily repeatable. For my CLIs, I started building them using command-line arguments, but I quickly forgot the arguments and order. Next I used configuration files, but then that tied me into a specific file or set of files for different operations. Eventually I started using an npm module called prompts that allows me to prompt for all of the configuration options either as the only input into the program or for writing the settings to a default configuration file. Yesterday I spent some time figuring out how to do conditional prompts, so that's the topic of this post.\nMy Node CodeYou can find all (most?) of my node.js modules on https://johnwargo.io/node.\nPrompts is pretty cool and very easy to use. The documentation is very helpful, but it could be a little more comprehensive.\nTo use it, you create an array of prompts like this:\n\nNext, you call the prompts() function like this:\n\nWhen that code finishes, the config object returned contains properties for all of the prompts using the value in the prompt object's name for the property name. Here's an example from the previous code:\n\nFor my particular use case, I wanted to prompt the user to specify a file format and output file name but only if the user selects yes for the saveToFile prompt. Prompts doesn't support conditional prompts (that I could discern anyway) so I had to come up with my own mechanism.\nThere's nothing keeping me from doing as many prompts as I wanted, loading in different prompt object arrays as necessary. What I didn't want was a clunky way of maintaining all of the configuration values. I came up with a simple and elegant approach (I think anyway) that worked first time.\nTo do this, I created two prompt arrays. The main one (prompt1) that executes every time the CLI runs and a second one (prompt2) that I execute only if the user selects Y for the saveToFile prompt.\n\nThe following code highlights how I executed the two prompts in series:\n\nWhen the first call to prompts() completes, the config object contains all of the user's responses/selections from the prompt. All I have to do is check config.saveToFile for true (y) or false (n) and act accordingly.\nRather than tracking two different configuration variables (config and configAlt), I simply used the following code to merge the properties of both into the existing config object:\n\nAnd here's the merged config object with the results of both prompts:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Node.js",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Amazon Delivery in 2036",
  "date":"Sat Nov 09 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1731196800,
  "url":"/posts/2024/amazon-2036-delivery/",
  "content":"Imagine my surprise when I received an email from Amazon letting me know that an album I purchased a while ago, (Opeth's Last Will and Testament), wouldn't be delivered until 2036.\n\nThe album was due earlier in the year, but the band recently announced it was delayed to November 22nd in 2024.  I'm truly curious what would delay the album 12 more years. Any ideas?  I'm not sure I want to wait that long to hear their new music.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Adding Sidebars to an Eleventy Site",
  "date":"Sat Nov 02 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1730592000,
  "url":"/posts/2024/adding-sidebars-eleventy/",
  "content":"I decided recently that one of the things missing from this site was the ability to have call-outs in the content. My buddy Scott Good was here this weekend working on something in my workshop, so, while we waited for some glue to dry, I asked him to add some call-out CSS to the site. After he left, I added some code to the site to make it all work.\nThis site uses Markdown files for posts and Markdown already supports Blockquotes:\n\nThe blockquote element represents a section that is quoted from another source. Content inside a blockquote must be quoted from another source, whose address, if it has one, may be cited in the cite attribute. If the cite attribute is present, it must be a valid URL potentially surrounded by spaces.\n\nThis allows me to create indented text, but it doesn't feel like a call-out or sidebar.\nWhat I wanted to be able to do is take content from the article and generate something like the following from it:\n\nThen, with the appropriate styling, it will look something like this:\nSidebar TitleBrisket meatball shoulder prosciutto pork loin shank ham. Capicola short loin ground round pork chop, jowl filet mignon spare ribs pork belly tri-tip kielbasa sausage t-bone drumstick cupim. Landjaeger ham biltong, prosciutto corned beef meatball pork belly pig porchetta turducken. Shank pork chop jowl tail.\nImplementing Sidebars As Shown\nScott added some CSS styling to the site:\n\nI originally wanted this sidebar thingie to be a sort of What it Means (WIM) block on the page, so that's why the styles have wim in them.\nNext, I added a paired shortcode to the site:\n\nThe code generates the HTML block shown at the top of the article with the required wim class assignment.\n\nThe code accepts a sidebar title, but if I omit one, it uses &quot;What It Means&quot; instead.\nThen, to use it in an article, I simply do this:\n\nWhich generates the side bar shown at the end of the previous section.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "No Posting",
  "date":"Mon Oct 14 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1728950400,
  "url":"/posts/2024/no-posting/",
  "content":"Wow, no posts from me in a while. I apologize for that, but I've been spending a lot of time in my workshop making sawdust, and I've not had much I wanted to blog about.\nI noticed that I had some issues completing projects in my shop, so I spent two solid months there finishing up some projects. I did a lot of cool stuff and solidified a lot of my skills (along with buying a lot of new tools - don't tell my wife).\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Flame Throwing Pumpkin",
  "date":"Mon Oct 14 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1728950400,
  "url":"/posts/2024/flame-throwing-pumpkin/",
  "content":"Back in 2019, I decided to finally start work on a Flame Throwing pumpkin project for Halloween. I saw some projects like this in the past, and I wanted to do my own version. Some projects do some pretty sophisticated things to make a flame thrower in a pumpkin (like using a solenoid to push down the nozzle of a spray can (hair spray or WD-40)) but others use a simple air freshener (short spurt) in front of a candle.\nI built my pumpkin out of a steel coal bucket because I didn't want to have to carve a large pumpkin every year. I also mounted it on top of a large monster frame to put the flame way above any children's heads.\nAnyway, I used this project for several years now, but realized I never published the source code. I finally got around to that yesterday, you can find it here: Sparky, the Flame Throwing Pumpkin.\nHere's a video of one of my first tests of the flame throwing mechanism\nAnd here's a full demonstration by our exchange student (at the time) Jannis:\nhttps://youtu.be/NKz0V5vYwB8?si=Gw-L9_2vB_EBNYtp\n\nAs I prepared for this Halloween, I decided to kill the whole 8 foot tall pumpkin monster and instead build a 48\" tall pedestal for just the pumpkin portion. I also thought about refreshing the code, but I decided to put that off until after Halloween this year. My plan is to migrate the project to an ESP32 device and a web app instead of using the remote control relay device. Stay tuned for details on that one.  \n\nHere's some pictures of the project; click on each to see a larger version of the photo.\n\n                                                import PhotoSwipeLightbox from '/assets/js/photoswipe-lightbox.esm.min.js';            import PhotoSwipe from '/assets/js/photoswipe.esm.min.js';            const lightbox = new PhotoSwipeLightbox({                gallery: '#gallery-sparky-1',                children: 'a',                showHideAnimationType: 'zoom',                pswpModule: PhotoSwipe            });            lightbox.init();              \n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Cloned Tool Shopping",
  "date":"Tue Jul 23 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1721779200,
  "url":"/posts/2024/woodworking-cloned-tool-shopping/",
  "content":"\nNote: I moved all my woodworking posts to my new woodworking blog at fumblyworkshop.com.\n\nAs you probably know from this site, I'm a geek and a software developer. I'm also a woodworker and it feels like I'm going to pull in more woodworker stories this year - mostly because I've been doing more woodworking than coding lately.\nI recently discovered Woodpeckers Precision Woodworking Tools and I really love their stuff. It's really (really, really) expensive, but I like that it's US Made (Ohio) and seems to be good quality stuff (it would have to be at those prices). I've experienced some quality issues with lately, so I'm starting to look for alternatives.\nI'm replacing the quickly thrown together wooden storage drawers I use in my shop. I made them 20 years or so ago and frankly I'm embarrassed of them. I've been playing around with two different finger joint jigs, so I'm in a position where I'm ready to start making some new drawers.\nOne of the things I know I want to do for these boxes is use library card deck like pulls to pull them out from the shelves. Thinking through that, I realized I needed a reliable way to attach the pulls to the drawer faces so I started looking for jigs to use.\nOf course, I started at Woodpeckers, but quickly realized that for the amount of use I was going to get out of it, it wasn't worth the expenditure. $219 is way too much for something like this unless you use it weekly.\n\nI knew there were some companies that cloned Woodpeckers tools, so quickly started looking around. I discovered Levoite a while back and knew they very deliberately cloned Woodpecker products. For their site, they generally copy the product images from the Woodpecker site then Photoshop out the Woodpecker name from product images.\nIn this case, their Woodpecker clone is $147.59 but they're going to let me have it for $92.99. Not bad, and I almost purchased it.\n\nYesterday, I discovered a company called Trek Drill that had a very similar product. The pictures are different at least, but it looks like the exactly same product.\n\nI've also been buying a lot of electronic components and some tools and parts from Ali Express, so hopped over to their site to see what I could find. There, the same product is only $18.62. Recognizing that I'd only use this tool rarely and maybe only enough times to build my 14 drawers or so, I went ahead and purchased it for less than $20 with shipping.\n\nI wish I had the expendable cash to buy each one and compare them, but I don't.\nI did recently purchase a Chamfer Plane from Levoite; I saw it on the Woodpecker site and it looked interesting. But, again, I wouldn't use it more than once or twice a year, so I went with the cheaper version. The quality is much lower than what I'm used to from Woodpeckers, but I'm not (yet anyway) a professional woodworker. Once I'm retired and regularly making furniture, I might then invest in the Woodpecker version.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking"
  
  ]
  },

  {
  "title": "Oval Router Template",
  "date":"Sat Jul 13 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1720915200,
  "url":"/posts/2024/woodworking-oval-router-template/",
  "content":"\nNote: I moved all my woodworking posts to my new woodworking blog at fumblyworkshop.com.\n\nOver the US 4th of July holiday, we were hanging around with family when my sister in law mentioned that she wanted to get an Owl House for her back yard in order to attract an owl to live in her yard. I'd never made an Owl House before, so I quickly volunteered to make one for her.\nAfter a little bit of research, I learned that the Cornell Lab of Ornithology publishes a catalog of birdhouse plans at Nest Watch: All About Birdhouses. All you have to do is select the bird you want as backyard company, provide an email address, then download the plans.\nMy sister in law wanted a house for an Eastern Screech Owl, so I quickly downloaded the plans and got to work.\nOne of the requirements for the house is an oval shaped hole on the front of the house for the bird to use to enter and exit the house. With that requirement in mind, I started thinking about how I'd cut that oval.\nI use the Router in my shop a lot and because of that I had a set of Rockler Circle/Grommet Templates that I can use to cut a circular opening on the house. The plans specifically call out that you can use a circle instead of an oval, but I wanted to do this right and figure out how to successfully (and that means do it so it doesn't look like crap) cut an oval hole on the birdhouse.\nI have a 3D printer here, so I quickly opened TinkerCad and cranked out an oval piece to the dimensions I needed. With that in hand, I knew I could trace the hole on the front of the birdhouse using the oval piece I just made, then cut it out using a jigsaw. That would work, but it's hard to stay in the lines with a jigsaw. Since I wanted to impress my sister in law with my woodworking skills, I abandoned that approach.\nThat's when I realized that I could make a Router template to cut the oval just like those circle templates I mentioned earlier. I quickly reopened my oval project in TinkerCAD and inverted it into a template I can use with my router:\n\nNow, the original oval piece was 3x4 inches, but when working with a router, I had to take into account the thickness of the router bushing (shown below) used to hold the router and bit within the template. So I measured the distance from the outside of the bushing (shown below) to the outside edge of the straight router bit (not shown, sorry) I used with the template. I used the Short Shank Guide Bushing and Nut, 5/8&quot; for this project (because that's what I had in my shop).\nThat distance is 1/8th of an inch, so I added that to all sides of my oval in the template, making the templated oval 3.25&quot; by 4.25&quot;.\n\nI made the overall piece 5&quot; by 5&quot; and printed it to my printer.\n\nThe print worked like a champ, so I took it down to my workshop to put it to work.\nThe following image was taken after I completed cutting the oval, but it shows how I setup the template before I started cutting. I used two-sided woodworking tape to hole the template in place on the owl house front panel. Using a plunge router and a small template, you don't have any room to clamp down the template to keep it from moving during routing. The tape kept in place and I was able to cut the hole successfully and cleanly.\n\nWhen I routed the hole, I used clamps to secure the cutting area off of the edge of my assembly table - so I wouldn't cut my assembly table top.\n\nThe only problem I encountered was that I didn't make the template large enough. I should have given myself three inches in all dimensions as a solid base for the router.\nI published the template on Thingverse; please let me know if this helps you.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Woodworking",
  
    "3D Printing"
  
  ]
  },

  {
  "title": "Google Functions Deploy Module",
  "date":"Wed Jul 10 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1720656000,
  "url":"/posts/2024/google-functions-deploy-module/",
  "content":"A while back, I published an article called Google Cloud Multiple Functions in a Project demonstrating some code I wrote to help Google Cloud Functions developers more easily deploy multiple functions with a single terminal command.\nThe code works great for me, since I only really have a single Google Cloud Functions project I work with regularly. If I worked with multiple functions projects, I'd have to copy that custom code from project to project and that just seems silly.\nThat stared me thinking about building that code into a node.js package I could install globally, then use it in multiple Google Cloud Functions projects without having to copy code around. I had some extra time the other night, so I created a new node.js project then migrated the existing code into a simple CLI.\nThe package is Google Functions Deploy (on npm) and you can find the source at github.com/johnwargo/google-functions-deploy.\nThe idea here is that you can group multiple Google Cloud functions into a folder with a separate subfolder for each function (functions project). With that in place, any code that deploys the functions merely needs to loop through the separate functions folders and execute the appropriate gcloud functions deploy command (with additional parameters determined by the developer based on their project) in each folder sequentially.\nConfiguration\nTo accommodate a project folder with more than just function project subfolders in it, the package uses a configuration file property called functionFolders to define the array of subfolders that contain functions projects. Google's gcloud functions deploy command also accepts a plethora of command-line options and rather than building support for all of them as configuration options, the package uses another configuration property flags to define the array of required command-line parameters needed to successfully deploy the functions projects.\nHere's a sample configuration:\n\nWhen you execute the package's CLI command the first time in a project folder, it offers you an opportunity to automatically generate the configuration file and even select the project folders names to use to populate the functionFolders array.\nExecution\nExecuting the deploy command is easy, just open a terminal to the project folder and execute the following command:\n\nThat's it. It loops through all of the folders and deploys each of the functions in sequence.\nPlease let me know if you find this helpful.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Cloud Development"
  
  ]
  },

  {
  "title": "Spam Chase Auto Pay Disabled",
  "date":"Tue Jul 09 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1720569600,
  "url":"/posts/2024/spam-chase-auto-pay-disabled/",
  "content":"I received another supposed Chase Bank Phishing email the other day and thought I'd spend some time analyzing it.\nThe Message\nHere's the email I received:\n\nAnd here's the content from the email (just to help search engines find it):\n\nAuto Pay Disabled #141655165\nImportant Update: Check Your Notification Center Now\nWe  are pleased to inform you that our notification servers have been successfully upgraded. Kindly log in to our notification center to verify your details and ensure the seamless processing of your scheduled bills and automated transfers.\nGo to Notification Center\n\nInitial Take on the Email\nI know it is spam or a phishing attempt because:\n\nI'm not a Chase customer (I was, but I'm not anymore).\nI don't have any auto pay setup with Chase (you know, because I'm not a customer).\nChase wouldn't send me an email addressed to &quot;Dear john@someaddress.com&quot;; if I was a customer, I know they'd address the message using &quot;Dear John&quot;\n\nThe next thing that caught my eye was the Service Mark (sm) in the sender email display name. Nobody does that, especially Chase Bank (I went back and checked some old emails I have from them):\n\nChase℠NotificationCenter info@racinglubes.com\n\nDomain Issues\nThe next issue, of course, was the actual sender email address: info@racinglubes.com. I could be wrong, but I doubt that Chase Bank would send me emails from racinglubes.com. Double-checking the domain, I noticed that when I navigate a browser window to that domain, it redirects to a real company (I think anyway) at racinglubes.fr. That Unlimited Source of Oil has nothing to do with Chase Bank as far as I can tell.\nNext, I started looking at the links on the page - they all point to the same racinglubes domain.\n\nhttp://r.mailing.racinglubes.com/mk/cl/f/sh/WCPzyXJTZ6uvfgsK2azUUqgbikbtf74M/wFiEJE1XEtCY\n\nLooking at the domain registration, it looks like a valid registration - created back in 2011. So that one has me a little confused since it doesn't feel like a Phisher would register their phishing domain 13 years ago.\n\nAnyway, testing the link and I get a broken link page with the following content:\n\nI think this means that I just validated my email address for the Spammer/Phisher. The link had a payload, the WCPzyXJTZ6uvfgsK2azUUqgbikbtf74M/wFiEJE1XEtCY in the URL, so I imagine they're able to associate that ID with my email address and update their internal system to show the email address is valid.\nThe big block of code in the img tag is the image file displayed on the page.\nPostscript\nA few days later, I received a very similar email, but this email's links point to r.mail.mycaptain.in with a completely different experience. That domain forwards to brevo.com/.\nSurprisingly, this phishing email has an actual email address as the sender: sruthi.r@mycaptain.in - I wonder if that points to the actual person who sent the email? I'm not going to reply to the email, but you can if you want to.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Connection Request",
  "date":"Mon Jul 08 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1720483200,
  "url":"/posts/2024/connection-request/",
  "content":"I don't understand some of the connection requests I get on LinkedIn. I received one today that reads:\n\nJohn Hi! Judging from your LinkedIn profile, you have achieved a lot in your field of work. I hope we can chat, and I look forward to our conversation!\n\n\nNow, my LinkedIn Profile clearly states:\n\nI restrict my LinkedIn connections to people I know, and have worked with professionally; if I do not know you, I will not accept your connection invitation.\n\nWhich means, I'm fairly certain, that I won't accept random connection requests unless, of course, I actually know the person requesting the connection.\nDigging deeper, I see that the requesting person has the following description in their LinkedIn profile:\n\nLP is engaged in freelancer. Started clothing, skin restoration, established clothing company, involved in wine, real estate, horse farm investment\n\nLP? I thought the connection request was from Anna Liu.\nOn top of that: Clothing? Skin Restoration? Wine? Real estate? Horse farm investment? Why would I be interested in any of that considering what's in my LinkedIn profile today? I just don't get it.\nLooking at their profile, it was created in 2013, but never posted anything to their profile in all those 11 years.\nI assume this is some sort of scam, but I can't figure it out. Some sort of franchise opportunity? A recruiter? Who knows, I declined the invitation, so I guess I'll never know.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Generating Post Descriptions Redux",
  "date":"Sun Jun 30 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1719792000,
  "url":"/posts/2024/generating-post-descriptions-redux/",
  "content":"I just finished publishing the previous post (about 3D printing) and realized I forgot to set a description for the post. Being rather lazy and remembering that I have a Describer GenAI extension for Visual Studio Code, I decided to let GenAI set the description for that post.\nA couple of clicks later, VSCode added a nice description to the post and I published it. It only took seconds, and I'm fairly happy with the results.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Artificial Intelligence"
  
  ]
  },

  {
  "title": "3D Printing Paradise",
  "date":"Sun Jun 30 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1719792000,
  "url":"/posts/2024/3d-printing-paradise/",
  "content":"During the pandemic, I convinced (begged and pleaded with) my wife to let me buy a 3D printer &quot;for the family!&quot;  I always wanted one, and I saw two years at home locked in with my family as a chance to actually get one. My former manager at Microsoft recommended an I3 printer and it was a great starter printer for less than $300, so I quickly ordered one. I don't think my former manager liked me very much, so perhaps that guided his recommendation, but the recommended I3 was definitely a starter printer.\nI struggled for a long time to print consistently and never quite achieved it. I was able to print a lot of things, but the quality was low and manually leveling the print bed was a pain in the @ss. I eventually just stopped using the printer, mostly because air currents in my office seemed to mess up my prints.\nFast forward to Thanksgiving 2023 and Bambu Lab had a Black Friday sale on the P1S printer. I convinced my wife I needed a new printer and that the prices available today on the reported best printer on the market were the lowest they were going to be for a while (that turned out to be true). With spousal blessing, I purchased the P1S and got to work.\nThere are many things about the printer that I love:\n\nIts enclosed, so I don't have to worry about my office air conditioning messing up the print.\nIt self-levels, so I'll never have to manually level a print bed again.\nIt prints 256mm x 256mm x 256mm which is essentially 10 cubic inches\nIts fast as hell.\n\nMy daughter is a huge cosplayer and one of the things I'd hoped to do was get her interested in using the printer as well. That definitely happened, my daughter's printed more than I have since I purchased the printer. I can't tell you how many times she's had that printer running all day and night printing Mandalorian armor pieces (helmets, shoulder pads, thigh pads, guns, and more).\nWhen I bought the printer, Bambu offered a discounted Filament club membership for 6 months, but they recently abandoned that and offer bulk pricing to anyone. Since November, I've easily purchased 30 or more spools of filament.\nAnyway, my daughter recently started printing less frequently, so I found some time to print some stuff myself (as I wrote in Bench Power Supply Project). I desperately want to learn how to design my own models, but I'm very impressed by the amount of really high quality models out there - completely free for my use.\nYears ago, I purchased the T5 e-Paper display unit. I run the weather app on it and I wanted to build a wooden enclosure for it. Yesterday, I pulled out the Rockler Router Table Box Joint Jig I purchased more than a year ago and set about creating a nice maple box for it. Building the box using the jig was amazingly simple and in no time I had what I needed.\nUnfortunately, due to the design of the board/display in the T5 unit, fitting the display in the box I made wasn't going to work. For some bizarre reason, the folks at LilyGo expose buttons on the top of the board and run a USB-C connector on the bottom of the board, so making all that fit in a simple box simply wouldn't work.\nSo, firing up my search engine of choice, I started looking for free 3D printer plans for a case for the device. I found hundreds. I downloaded a few and I'm in the process of printing them to see which one I like the best. The quality of these prints are just amazing and handle the exposed buttons and inappropriately placed USB connector fabulously. I'll try to remember to show you when I did once I get it all mounted up in the selected enclosure.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Project Builds"
  
  ]
  },

  {
  "title": "Spam Chase Bank Autopay Halted",
  "date":"Fri Jun 28 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1719619200,
  "url":"/posts/2024/spam-chase-bank-phishing/",
  "content":"I received an email the other day that I was certain was a phishing attempt; here's the email message:\n\nInitial Take on the Email\nI knew it was a phishing attempt because:\n\nI'm not a Chase customer.\nI don't have any auto pay setup with Chase.\nChase wouldn't send me an email addressed to &quot;Dear john@someaddress.com&quot;; if I was a customer, I know they'd address it &quot;Dear John&quot;\n\nDomain Issues\nIt's pretty easy to tell from those few things that this isn't an email I should act upon, but I sure want to tear it apart. Looking at the from address in the image, notice that it's supposedly from mazon.sp.org.br. That's interesting because If I actually was a Chase customer, they wouldn't send send me an email from that domain, they'd send it from something that ended in chase.com.\nIt is funny that these guys would make it look like it came from Amazon (it didn't) considering it's supposed to be from Chase Bank.\nBesides, if I was a Chase customer, I'd likely be a customer of theirs in the US, not in Brazil (the .br ending on the sender domain name). And, if I was a Brazilian, why would the domain have sp in it (which indicates Spanish language) especially since the message to me is actually in English.\nLink Analysis\nTaking a look at the link behind the Get Started button in the email; it points to notifications-center dot su. When I lookup that domain at https://who.is/whois/notifications-center.su, here's what I get:\n\nNotice that its registered to a private person, not Chase Bank as you'd normally expect.\nYep, this is a phishing email. Now, I wonder what happens when you click the link?\nI fired up VMWare Workstation and loaded a new Windows VM, opened the browser and entered the URL, but whatever site was there has already been pulled down.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Repeating Countdown Timer in Flutter",
  "date":"Wed Jun 19 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1718841600,
  "url":"/posts/2024/repeating-countdown-timer/",
  "content":"A while back, while anticipating a particular event (my retirement), I decided to create an app that allowed me track the number of days until the event. One thing led to another and I decided to create a more generic version of the app so I could write about it here.\nYou can find the complete application code at Repeat Countdown Timer (Flutter).\nI created the app using Google's Flutter mostly because I love working in Flutter and it allows me to create an app that runs on almost any platform.\nIn the app's current form, you must hard code the event month and day into the app as integer constants as well as the event name as a string\n\nWhen you run the app, it keeps a running countdown until the selected event date tracking Days, Hours, Minutes, and Seconds until the selected date. When the clock reaches the specified date, the counter resets and starts tracking the next year's event.\nHere's a screenshot of the app in action:\n\nDigging Into The Code\nStyling\nThe app uses some constants to control app styling; you can tweak those to your particular needs.\n\nManaging State\nThe app tracks the event date and updates whenever it changes. If I wanted the app to track only a single date, I'd make it a constant and not worry about tracking state of the variable in the app, but in this case the event date resets every year, so I had to use State to track it.\n\nThe app uses the timeDiff variable to track the difference between the current date and the event date. Dart provides a Duration object that stores the time difference in days, hours, minutes, seconds, and milliseconds. Once I had my hands on that, building out the app UI was easy.\nThe Timer object fires every minute and executes the following code:\n\nAs soon as the number of seconds becomes negative, the app resets the event year so it can start counting down to the next event.\nBuilding the UI\nSince I had repeatable UI elements (all some variant of the Duration object - days, months, etc.) I created a simple widget that displays the value and updates every time the difference changes.\n\nWith that in place, all I had to do was create the app screen and throw in some of those widgets (configured, of course, for the Duration value being tracked by that widget). Here's the code:\n\nWrap Up\nI played around with adding milliseconds to the app, but it really didn't seem necessary to track things at that level. Besides, I'd have to change the timer to fire every 100 ms or so and that would put an unnecessary tax on device performance and battery life.\nI hope you find this app useful.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Flutter",
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Ali Express Parts",
  "date":"Tue Jun 18 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1718755200,
  "url":"/posts/2024/ali-express-parts/",
  "content":"In my previous post, I mentioned that I like building electronic projects I find online. Historically, I purchased a lot of project components from online vendors like Adafruit and Sparkfun. Both offer their own proprietary boards as well as some standard electronics components you can use for your projects (such as battery connectors, cables, breakout boards, other connectors).\nIt seems to be harder lately to find simple components I need on Adafruit's site while I don't buy that frequently from Sparkfun anymore. I found that a lot of the things I need I can get from Amazon now and I can get them almost immediately (same day, in some cases) and usually shipped for free.\nWhen I built the bench power supply, and some other projects lately, I found that it became much easier to locate a huge variety of electronics components at a very reasonable price with free or very inexpensive shipping on Ali Express. Lately I've been buying switches, connectors, batteries, and more in bulk for pennies on the dollar there against buying them on Amazon or Adafruit.\nCase in point: years ago I looked for panel mount USB connectors I could use for my microcontroller projects. My thought was that for many of my projects, I didn't want the microcontroller USB connector bumped up against the side of the enclosure, I wanted to put a USB connector on the back of the enclosure (hidden away) and only use the microcontroller connection when programming the board (deploying a sketch, for example).\nI hunted around and finally found some on one of those large component vendor web sites (I don't remember which one, I think perhaps DigiKey or Mouser) but they were $14US each and, with shipping, much too expensive for me to stock up on.\nFast forward a couple of years and I specifically went looking for USB connectors on Ali Express and found so many different options at incredible prices. Take a look at the two bags below, each contains 50 panel mount USB connectors with pigtails in two different styles and I was able to purchase the whole lot, with shipping, for about $20US.\n\nIt's just amazing. I've even started looking there for larger electronics too like LASER engravers, Reflow Ovens, hot air rework stations, etc.\nAnother interesting about buying from Chinese vendors is that they've started using shipping companies in the US for in-country delivery. For a lot of purchases lately, the packages go to a US company who repackages it (or at least relabels it) for US shipping, using USPS for the last mile(s). Folks like Olight (excellent flashlights), Seeed Studio (yes, three e's, not a typo) and others seem to do this as well and it seems to work pretty efficiently.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Project Builds"
  
  ]
  },

  {
  "title": "Bench Power Supply Project",
  "date":"Sat Jun 15 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1718496000,
  "url":"/posts/2024/bench-power-supply/",
  "content":"I'm a big fan of Instructables and regularly watch their newsletters for interesting projects. A few weeks ago, one of them caught my eye: Lab Bench Power Supply. This project seemed cool so I decided to build it.\nWhat I liked about this project was that it did a few different things I needed in my shop. I had a bench power supply on my workbench for some time, but it was variable power only, I had to dig out a phone charger whenever I wanted to power an Arduino device or Raspberry Pi. It also has a 3D printable enclosure and with my recent acquisition of a Bambu Labs P1s I knew I had the equipment I needed to build it.\nHere's the finished project on my workbench: \nThe project includes complete assembly instructions, which is nice, but not a complete part list with links to purchase the items. I found that I had to go digging around for the specific parts I needed. For example, the project's 2 single-pole round switches didn't tell me anything about the diameter of the switches. I purchased some switches I thought would work, but they were too big. After that failure, I measured the switch openings in the printed panels and hunted around for switches that were 14mm diameter (which took me a little longer to find).\nThe cornerstone component for the project is the Buck-boost 6-36V 80W voltage regulator with voltage and current meter. The link in the original article is broken, so I used a link there that shows a lot of similar devices - they're probably not all the same dimensions, so pick carefully. It's a really cool device that bundles a power converter (input) voltage regulator(output) with a built-in display and controls. Nothing to assemble here, just plug it into the enclosure, give it an input voltage (I used 12V) and you can easily control the output.\nThe author of the original project used an old laptop power supply to power the unit, but that approach:\n\nCreated the need for extra hardware components in the project to convert the input from the barrel connector to something that could be connected to the Buck-boost device and the USB Step Down converters.\nAdded a bunch of unnecessary wire into the enclosure (that two or three feet of wire from the power brick to the barrel connector).\n\nSince I didn't have an old laptop power brick laying around, I decided to take a different approach. For my implementation, I purchased the AC to DC 24V 100W Power Supply, AC 110~250V to DC 24 Volt Regulated Switching LED Power Supply, DC Transformer Adapter, Upgraded Power Driver for LED Strip, 3D Printer, Computer Project from Amazon. At 100W output, it can handle any output requirements from the unit. This particular device comes with two sets of output connectors, so I was able to easily route one set of wires to the Buck boost device and the other to the USB Step Down converters. This change dramatically simplified the internal wiring needs for the unit but I had to just lay the power supply in the unit awkwardly rather than use the tie downs in the enclosure.  If I knew enough about editing 3D Printer files (I know nothing), I'd modify them to make the enclosure a little wider to give me a place to stick the power supply against the back wall of the enclosure.\nAnother interesting aspect of the build was that I got to use brass screw inserts for the first time. I printed the enclosure using grey and black as shown in the figure, then used a soldering iron with a special attachment to push brass inserts into the support braces. With those in place, it was very easy to screw the whole assembly together. I thought that whole process would be hard, but it turned out to be very easy with the right tools. Here's the tool I used to to do the job: Heat-Set Insert Tips for Threaded Inserts M2 M2.5 M3 M4 M5 M6 M8, Soldering Iron Tips Compatible with Weller SP40NUS/Hakko FX-888D/900M/T18 Irons- Press Tool for Plastic 3D Printer Components. I'm really looking for an opportunity to do more with screw inserts in future projects.\nThe unit is assembled and functional and I've already put it to good use in my shop.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Project Builds"
  
  ]
  },

  {
  "title": "Windows Path Backup Utility",
  "date":"Fri May 24 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1716595200,
  "url":"/posts/2024/windows-path-backup-utility/",
  "content":"At the beginning of the year, I had a problem with my Windows Path and a bunch of my apps stopped working correctly or stopped working altogether. I poked around a bit and figured out what went wrong: my system path somehow got corrupted and, you know, broke my apps.\nYou can read about the original problem in Windows Path Items Not Available in Visual Studio Code and you can read a little about what I plan on doing about it in Windows Path Viewer App.\nAnyway, as I set about building a utility I could use to repair my system's corrupted Path, I realized that the first thing I needed was a way to quickly and easily backup and restore the system Path so I could test my repair utility while not harming my system's Path. The Windows Path isn't stored in an easy to access area on the system; first of all you need Administrator access to even see it and it's stored in the Windows Registry in two places, so there's no quick and easy way to save it to a file.\nSo, what I did was create a little Windows utility called Path Backup &amp; Restore (catchy name, eh?) that allows me to quickly and easily backup my Windows Path to one of three different file formats:\n\n.reg - The Windows standard Registry file format\n.json - JavaScript Object Notation (JSON) format\n.yaml - Yet Another Markup Language (YAML) format\n\nUsing the utility, you can backup the path to a file or use an existing backup file to restore the system path (replacing the existing Path entries).\n\nI chose supporting the .reg format because it allowed me to let Windows restore the Path using the file (a standard capability of the Windows RegEdit utility). This allows you to take a working Path backup and share it with another user who can restore it without needing access to the Path Backup &amp; Restore application.\nI added support for JSON and YAML files because I wanted to offer options and I wanted users to be able to access the files in an easy to edit format in case they wanted to manually edit a backup file then restore it.\nI wanted to release the application through the Windows App Store, but after getting almost all the way through the process, I finally realized it was too complicated (and possibly expensive) to sign my application securely for distribution. It just doesn't seem easy to do and wasn't setup for small development teams like me trying to distribute software through the store.\nNote: If anyone wants to help me figure out how to sign my app for distribution in the Windows App Store, please let me know.\nI decided to release the application through my recently relaunched software company Fumbly Diddle Software; please check it out when you get a chance.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Testing a Bunny.Net CDN",
  "date":"Sat Apr 13 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1713052800,
  "url":"/posts/2024/testing-bunny.net/",
  "content":"I built a Windows app that I'm trying to publish in the Windows App Store. As I worked through the publishing process, I made a huge mistake and didn't look for documentation that walked me through the whole process. Rather than getting all of my ducks in a row, I worked through the process bumping up against issue after issue. I feel like I'm getting nowhere.\nAfter getting my Microsoft store account setup and validated, I set about configuring my app profile only to discover that I needed a CDN. I've never had a CDN before; I've used them, but never setup my own.\nI started looking at the pricing page to determine what this would cost me, but I couldn't accurately assess my costs. Not knowing my costs is a problem, but since I had some Azure credits lying around, I started poking around in the Azure Portal to see if I could create one anyway. After following the instructions to create a CDN, I learned that neither my credits nor my pay as you go accounts were enabled for CDN creation. Strike 1.\nNext I Googled setting up a CDN and found that one of the top recommendations was Fastly. I started poking around on their site only to find that for every pricing package the only option was to Request Pricing. If they're not going to let me know what their service costs, I'm out. Strike 2.\nGoogle's next best option was a recommendation for Bunny.net and they actually publish pricing on their public web site. A quick look told me I'd pay a minimum of $1 per month and their other charges were very reasonable based on what I expected my needs to be.\nI have this first app to publish and another one following quickly, so I'm going to give it try to see how this works out. This will cost me a minimum of $12US and likely more - I'll either run this for a year and see what my overall costs are or kill the experiment when I reach something like $50US hosting costs for the year.\nI'll let you know how it goes.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Web Development"
  
  ]
  },

  {
  "title": "Postal Scam Urtye dot com",
  "date":"Sat Apr 13 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1713052800,
  "url":"/posts/2024/scam-postal-urtye/",
  "content":"I received an interesting text message yesterday that is clearly a scam. Just in case others received a similar message, I assume many did, this post tears down the message proving its a scam.\nHere's the message I received:\n\nNote: The (web address withheld for safety reasons) is my placeholder for the actual web address urtye dot com. I didn't want someone to accidentally click the link, so I removed it.\nI don't want to show the actual URL because I don't want to be responsible for someone clicking on it and getting hacked. Here's an image of the message with the full URL:\n\nLooking at this message, I was fairly certain it was some sort of scam or phishing attempt since the country code for the sender (+63 906 755 6259) is the Philippines. I don't expect to get text messages from the Philippines, especially since I've never ordered a package from the Philippines.\nI also know from reading a lot of Wired Magazine and other sources that the Philippines is the source of a lot of scams; for example: Hundreds rescued from love scam centre in the Philippines.\nAnyway, since I wasn't sure about this message and I didn't recognize urtye dot com as a safe domain, I did some more research. First I looked up the domain registration and found that the domain is registered via Alibaba Cloud Computing Ltd. d/b/a HiChina (https://net.cn).\n\nThat's interesting because I have some purchases on the way from Ali Express in China but since no additional information is available, like an order number or vendor, I'm still wary at this point.\nFinally, I opened up a Windows VM, took a snapshot of the system, then launched the snapshot. Once the system came up, I opened a browser window and typed in the URL from the text message. What did I get? The United States Postal Service web site.\nSo I'm pretty confused by this. I don't understand why someone would go to all the trouble to send me that message only to redirect me to the USPS web site. I double checked and the text message has that exact URL referenced at the beginning of this article. No hidden parameters embedded in it.\nI think what happened is that the hackers or scammers had a specific target in mind for the hack or scam and since I triggered the URL from a Windows desktop browser (and they were looking for an Android or iOS device) that the target site simply redirected me to the USPS web site. I'm not going to click the link on any of my mobile devices, so I guess I'll never know what would happen.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Using the DFRobot I2C 16x2 LCD display",
  "date":"Fri Apr 12 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1712966400,
  "url":"/posts/2024/dfrobot-i2c-16x2-lcd-display/",
  "content":"I'm a fan of many products from DFRobot and they occasionally gift me with newer products to use and write about here. I'm working on something now that leverages their Gravity: Lightning Distance Sensor and I wanted to use a display to show lightning distance. For this I'm using the I2C 16x2(1602) LCD Display Module for Arduino and as I started to build the project, I wanted to test the LED display separately to learn how to write to it. I ran into some problems with the DFRobot Wiki and drivers for the board, so I decided to write this post to help others get through the same issues.\nConnections\nStarting at the I2C_TWI_LCD1602_Module__Gadgeteer_Compatible___SKU__DFR0063_-DFRobot I immediately noticed a problem. It may be fixed by the time you read this, but the connection diagram on the page is for a completely different product (I can't even tell what it is - something to do with a robot).\nSo, to understand the connections, I looked to the back of the display and found the I2C connections properly labeled on the board.\n\nTop to bottom, the connections are:\n\nVCC\nGND\nSCL\nSDA\n\nConnect those pins to the corresponding pins on an Arduino device and you're all set.\nLibrary Installation\nIn other wiki tutorials, DFRobot links to the library source with instructions for how to install the required library (or libraries) in the Arduino IDE. I looked for those instructions and didn't find them and almost missed the link labeled Sample Code and Library just inside the Sample Code section of the Wiki.\nDownload that file and unzip it into your Arduino libraries folder on your system. To locate your system's Arduino Libraries, open the Arduino IDE, then open the File menu and select Preferences. The Sketchbook location field contains the location of the system's Arduino folder, the libraries folder should be right underneath that folder (Arduino/libraries).\n\nAlternate Library Installation\nIf, for whatever reason, you don't want to install the LCD display library in the Arduino IDE, you can also install the files directly in your project folder as shown below:\n\nTo do this, I extracted the files in the download and copied the contents of the LiquidCrystal_I2C folder (skipping the examples folder) into my project folder. With that in place you have to make one change to the sample sketches. Change the line that loads the library in the sketch from:\n\nto:\n\nThis tells the IDE to load the library locally instead of pulling it from the libraries folder.\nHere's the complete modified sample code, so you can copy it into your local IDE if you want:\n\nRunning the Code\nWith the library extracted to the correct location and everything wired up as described above, the sample code I found (both sketches) worked perfectly on my system.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Amazon Digital Music Hell",
  "date":"Thu Apr 11 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1712880000,
  "url":"/posts/2024/amazon-digital-music-hell/",
  "content":"Amazon sent me an email this morning letting me know that a digital album I purchased was available for download. You'd think I'd be able to click a link and download my purchase, but you'd be wrong.\nTake a look at the email. The first link is supposed to be a link to download the music from my library.\n\nWhen I click on the link, I get the following page:\n\nWell that's not good. Let me see if I click the order details link:\n\nOK, that works. So when I click the Launch Music Library button it's going to take me to the downloads for my most recent purchase, right?\n\nOops, nope. The first thing I see is a pitch to pay more to gain access to millions of songs. I'be been buying digital music from Amazon for years and they prompt me like this EVERY SINGLE TIME I open the app. You'd think that after likely hundreds of No's they'd realize I'm not going to sign up and stop asking me. Nope, the product manager for this obviously isn't paying attention to the telemetry from this feature.\n\nAfter I dismiss the sales pitch I've seen a hundred times or more, the app opens and shows me some of the bands I've purchased in the past, but then a bunch of artists I know nothing about. I'm into the blues and southern rock (among others) how did I get a station listing musicians I've never heard of. That list should all be progressive rock, blues, folk, rock, heavy metal. Such a horrible experience.\nAlright, so I'm here to download my latest purchase. Where do I do that? I clicked on Library to bring up my, you know, library and this is what I see.\n\nAlright, I think I'm almost there. I clicked on Purchased and FINALLY the album I purchased shows up.\n\nA few questions:\n\nWhy did this have to be so freaking hard?\nWhy if I just purchased the latest album from Mark Knopfler do they recommend artists in, from what I can tell, a completely different genre? Amazon has telemetry that tells them what type of music I listen to, why not use that data to craft a list that would interest me instead of assuming I'm a twenty-something dude listening to I don't even know what type of music that was they recommended.\nWhy can't the download link from the email and the order details page take me to the download?\nWhy did I have to click 18 times to download 9 music files? Where's the freaking Download Album?\nWhy doesn't someone setup a test process that validates download emails added to emails. I've done this 20 times or more, the links never work but Amazon doesn't seem to know or care.\n\nNow, one of the things I tried to resolve this was go to my orders page and there was a button labeled Download Music that should be able to help me, right? When I clicked on the button, the actual button that should allow me to download the entire album as a single file. What did I get? See below.\n\nMy point here is the whole Amazon music thing is seriously broken and since Amazon doesn't provide a forum where I can let them know, I'm writing about it here.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Amazon Digital Music Hell Continued",
  "date":"Thu Apr 11 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1712880000,
  "url":"/posts/2024/amazon-digital-music-hell-continued/",
  "content":"Earlier today I posted a rant about the ridiculous customer experience I encountered purchasing digital music from Amazon. If you've read many of the posts here, you probably noticed that I sometimes go off the handle on a topic and don't always think it completely through. After my online rant this morning, I started thinking of the possible reasons why an Amazon Digital music link would fail and I came up with some ideas.\nHere's a link to the original article.\nI have the Amazon music app installed on my primary system (Windows 11 x64) - not because I listen to music on it, but because I assumed it would be an easy way to download digital music purchases. It's not. Since I don't listen to music using the app, I've shutdown (disabled) the startup apps that run in the background listening for who knows what (see picture).\n\nI thought perhaps the email link was trying to launch the app and that &quot;Amazon Music Helper&quot; app was how they did it.\nSo I re-enabled it, rebooted my system, and tried the email link again.\nFailure.\nOK, so next step was to assume that Amazon assumed I open all of my email on my mobile phone (I don't). I quickly opened my email, found the link, tapped it, and the browser immediately opened then displayed the same error message.\n\nSo I'm out of ideas. Apparently Amazon sends out broken links in emails and has no idea they're broken.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Added Timestamp to Posts",
  "date":"Sat Apr 06 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1712448000,
  "url":"/posts/2024/added-timestamp-to-posts/",
  "content":"In my previous post, I described how I updated my Eleventy New Post utility to add a timestamp property to new post's front matter. With that in place, I updated the site's Home Page, Articles Page and at the top of every Post. I encountered a little issue with that implementation related to time zones, so I decided to dig deeper into the implementation on this site and how I solved the time zone issue.\nHow I Implemented Timestamp in this Site\nThe first thing I did was add a filter called readableTimestamp to the site's eleventy.config.js. Well, that's not actually true, it wasn't the first thing I did, but it's the first thing I want you to know about the implementation.  Here's the code:\n\nWith this code, if you pass in a timestamp from the previous post's markdown file: 2024-04-06T12:10:59.445Z, the filter returns Saturday, April 6, 2024 at 08:10 AM. When testing this code on the site, everything worked great, but when I deployed it to my hosting provider the timestamp was incorrect. More on this later.\nNext, I updated the different layouts to display the timestamp property when there was one, but the date property when there wasn't. There are 500 or so posts in this site, but only the most recent ones will have a timestamp.\nOriginally, the site used something like this to display the post date:\n\nIt uses the readableDate filter from the eleventy-plugin-date plugin to format the date for output.\nNote: You may have noticed the name of the filter I listed above - I specifically picked the filter name to align it with the one from the Eleventy date plugin.\nTo implement the timestamp, I changed the code to look like this:\n\nThat's basically all there is to it.\nThe Problem\nLike said earlier, when I tested the site locally, all the dates appeared correctly. That's because I executed the Eleventy New Post (11ty-np) utility in GMT-4 (US Eastern Time) and served the site locally in the same time zone. As soon as I published the site to Netlify, the timestamp displayed 4 hours delayed. For example, 2024-04-06T12:10:59.445Z is 8:10 AM GMT-4 but also, at the same time, 12:10 PM GMT. Netlify's servers dutifully render the site using GMT and therefore all of my timestamps (there was only one at the time, but you get what I mean, right?) were off by 4 hours.\nWhat to do?\nThe Solution\nI started poking around at the code, looking for a way to convert the timestamp to my local timezone for all cases, but didn't come up with anything. Then I realized I'd bumped up against this earlier (although I couldn't remember what it was). A quick search and I found the solution.\nNetlify allows you to set environment variables to control the runtime environment. My site runs on a Linux server (I assume) and you can set a timezone environment variable (TZ) and force the server to think in a specific timezone.\nI could set the environment variable in the Netlify portal, but they also allow you to include variable definitions in a text file checked into the repository. I created the netlify.toml file shown below, checked it into the site's repository, pushed the code to the server, and the problem went away.\n\nThe site serves in America/New_York time zone (which updates automatically for Daylight Savings Time (I assume)) and I'm all set.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Added Timestamp to My Eleventy New Post Utility",
  "date":"Fri Apr 05 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1712361600,
  "url":"/posts/2024/new-post-timestamp/",
  "content":"A user of my Eleventy New Post utility submitted a feature request yesterday suggesting I add the post's timestamp to the generated post instead of just the date.\nIf you put a timestamp in a post's date front matter property, Eleventy ignores it since it expects that property to just be the post date. To implement this feature, I added a configuration option that causes the utility to add a new property to the post called timeStamp with the full date/time for the post creation.\nI also updated this site to use the timeStamp when available. Enjoy!\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Building a documentation Site Using Docusaurus",
  "date":"Fri Mar 29 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1711756800,
  "url":"/posts/2024/documentation-site-docusaurus/",
  "content":"As I mentioned in a post last week, I'm building a web site for my software company: Fumbly Diddle Software. Along with the site, I also need a place to publish product documentation. I thought I'd just build an 11ty site for both the product information, news, blog, and documentation but as I started working through all of that I decided that wasn't the path I wanted to take. I decided instead to use one of the documentation static site generators. I wanted to be able to work in markdown files like I do for my 11ty sites, but I also wanted something that took care of page navigation, search, and other capabilities for me automatically.\nI played around with a couple of the documentation site toolsets and finally settled on Docusaurus and you can see the simple site I created (only one product) at Fumbly Diddle Docs.\nTo learn Docusaurus, I created the standard tutorial site and started playing around with it. What's interesting is the getting started site delivers a full web site with pages, a blog, as well as documentation. The full site looked capable with a good looking template and a bunch of options for content. However, all I wanted was a documentation site, so the process of turning that getting started site into a solely documentation site consisted of pulling functionality out of the generated site. Once I deleted the pages and blog folder, the most complicated thing I had to do was get the site to open the documentation area by default.\nDocusaurus implements its configuration through a docusaurus.config.js file just like 11ty does with its eleventy.config.js file, so that was familiar to me. To make the site a solely documentation site, I first deleted the project's index.js file, then added the routeBasePath property to the configuration file as shown below:\n\nSomething else that really threw me, and caused me some extra debugging time, is configuring plugins in the site. Making the site installable as a PWA and implementing Google Analytics was as easy as adding a couple of plugins and setting some configuration properties, but what really threw me was the format of that configuration object:\n\nIts a JavaScript array, but it wasn't formatted like I expected it to be. Instead of property key/value pairs like this: &quot;property_name&quot; : &quot;property&quot;, the configuration object consists of an array of plugins and each plugin configuration is an array of a nameless property (I don't know what else to call it) for the plugin name followed by a configuration object for the plugin.\nWhat I expected to see was something like this:\n\nI've never seen a JSON Object rendered that way, but perhaps you have.\nAnyway, the site is up and operational, and I'm going to spend tomorrow trying to publish the app to the Windows App Store - wish me luck.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Static Site Generators",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Eleventy Navigation Set URL to First Item in Collection",
  "date":"Sat Mar 23 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1711238400,
  "url":"/posts/2024/eleventy-navigation-set-url/",
  "content":"I'm building a new web site for a software company I created using 11ty, and one of the things I want to do in this site is have the Products menu item open the product page for the first product in a sorted list of product pages.\nHard-coding a Navigation Menu URL\nThe site uses the Eleventy Navigation plugin, and as a potential solution for this. The plugin offers the ability to override the url for a specific menu item.\nThe way this works is you make a page on the site for the menu item and set the front matter's url property to the URL you want opened when a site visitor clicks the menu item. The URL can point to a local page or an external page, the plugin doesn't care as it's just a URL. Here's an example of this in action:\n\nThat example was taken from the site's Products page and its important to note that all this page does is populate the Navigation plugin's data about the site's menu structure, this page doesn't generate an HTML file in the project's _site folder. Eleventy reads the file, adds the Key, Order and URL to the site's navigation data set, then throws the file away.\nThis solution definitely works for my use case, but not the way I want it to. It works as long as I remember to change the product URL when I add a new product with a name that starts earlier in alphabetical order than the one I have hard-coded now. If I don't remember to do this, and I promise that I won't, then site visitors may be confused when the site's Products menu takes them to the middle product in the product list.\nNo, what I want here is a menu item link that calculates the URL for the first product in the site's product collection.\nCalculating the Menu URL\nIn this site, I tag each product with product, so Eleventy builds a product page collection for me I can access as collections.product. I know this works, because that is how I build the product list in the Products page sidebar:\n\nWhat I couldn't figure out was how to calculate the URL on the Products page. I knew I could use eleventyComputed to calculate it, but I didn't know how to access collections there. I reached out on the Eleventy Discord and asked for help with this; with the help of some others, like Shiv Jha-Mathur (Aankhen)) and Bob Monsour, we got it working.\nThe solution is to add data a file called products.11tydata.js to the project alongside the products.liquid file. With that file in place, I can calculate the URL there using JavaScript.\nThe first thing I did was remove the url property from the Products page:\n\nNext, in the products.11tydata.js file, with Aankhen's help, I create an eleventyCompted property that calculates the url like this:\n\nNow, before you run off and use this code in your project, note that it doesn't work for a couple of reasons.\nFirst of all, Eleventy sorts the product list by date, so that solution always pull the first product I created rather than the first product in alphabetical order. What I need is a sorted list, so I created a sorted collection in the project's eleventy.config.js file like this:\n\nI could do that work in the products.11tydata.js file, but since I know I need to list the product in order on the Products page sidebar, doing it there allows me to use the same ordered list twice in the site.\nThe other reason the eleventyComputed approach above doesn't work, and I have to admit that I really don't understand it, is that (from the Discord conversation):\n\nIt runs with placeholder values the first time so Eleventy can figure out the dependencies between different things and catch any loops. So you have to allow for that possibility in your code.\n\nBob Monsour came up with the solution, it looks something like this (slightly modified by me, but you can see the original on Discord):\n\nSince the code executes twice, it has to catch when it actually has a value to return then only return it then. Weird, I know, I'm still scratching my head on that one.\nThe first time the code runs, productCollection is empty, the second time it's not. In the early version of the code, I imagine what happened was that the code dutifully returned undefined where in the later version it rightfully returns the sorted product collection as expected.\nWhew, what an interesting solution and I learned a few things doing this. I especially love how the community helped me figure this out.\nAlternate Solution\nIn the solution above, the code checks to see if productCollection contains any values. That certainly works, but another possible solution is to check to see if productCollection is not undefined.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Delphi ListBox Move Multiple Selected Items",
  "date":"Fri Mar 22 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1711152000,
  "url":"/posts/2024/delphi-listbox-move/",
  "content":"I worked on a Windows application project in Delphi that required moving selected items around within a Delphi standard ListBox. It's pretty easy to swap single list item positions, but once you enable multiselect on the component, things become more difficult. As I poked around on the Internet for solutions, I couldn't find a complete example, so I decided to create and publish one. Here it is.\nHere's an image of the application in action:\n\nWhen you run the app, it opens with a list of random words paired into 2, 3 or 4 word phrases in the list box. Select one or more items in the list, then click the buttons to move the selected items to the Top or Bottom of the list or to move them up or down.\nTake a look at the source code to see how this works. I also published compiled executables just in case you need them. You can find all of the code in Delphi ListBox Multiselect Item(s) Move Demo. Let me know if you have any issues with the code.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi"
  
  ]
  },

  {
  "title": "Google Cloud Exposed Service Key",
  "date":"Thu Mar 21 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1711065600,
  "url":"/posts/2024/google-cloud-exposed-service-key/",
  "content":"At the beginning of the year, I published a post  called Leaked Credentials from Google Cloud Project that described an issue I had, well it was an issue I created, with my Google Cloud account. I wanted to show some Google Analytics stats on this site and the only way I, at the time, could figure out how to do it was to run some code at build time that collected the data I needed from Google's APIs and added it to the site. To do this, the code required an API key for my Google Analytics data. I created a read-only key and included that key in my site repository on GitHub. Google freaked out and sent me a series of emails yelling at me for what I did.\nNow, part of the issue was that Google setup its Analytics data SDK to require a big ass API key. I tried saving it as an environment variable, but I couldn't get it to work. My only option, based on how I chose to implement it, was to store the API key in the repository. I reasoned that since it was a read-only key, what harm could a bad actor do?  Right?\nAnyway, after being yelled at by the Google Cloud team for several months, I finally gave in and migrated the code to a set of Google Cloud Functions and made all of that code private. Problem solved and I learned a few things I was able to write about here: Google Cloud Multiple Functions in a Project and Coding Google Functions Using TypeScript.\nCool stuff.\nFast forward to today and I received yet another email from the Google Cloud team:\n\nDear John,\nWe’re writing to let you know that Google Cloud is introducing an organizational policy change on June 16, 2024. This change allows organization administrators to define how Google Cloud should respond if we become aware that a private Service Account Key has been publicly exposed. We are integrated with several programs, including the GitHub scanning program, to identify publicly exposed private Service Account Keys.\nWhat do you need to know?\nService account keys must be kept private, and exposing them publicly can compromise your Google Cloud environment. A compromised Service Account Key could be used by bad actors to access, modify, or delete your data and/or consume expensive resources. We understand this could be disruptive to your organization and we are taking proactive measures to protect your environment.\nTo enhance the security of your environment, this organizational policy change will take effect on June 16, 2024. This change will proactively disable any publicly exposed Service Account Keys that we become aware of. This will affect all uses of the exposed Service Account Key.\nWhat do you need to do?\nYou have the ability to modify this behavior ahead of time by taking one of the following actions:\n\nOpt-in early by setting the IAM.serviceAccountKeyExposureResponse constraint to DISABLE_KEY which will enable the protection immediately.\nOpt-out anytime by setting the IAM.serviceAccountKeyExposureResponse constraint to WAIT_FOR_ABUSE which will disable the protection.\nDo nothing, in which case Google will enable the protection on your behalf on June 16, 2024.\n\nAgain, we understand that these changes might require some planning, but they are designed to enhance security for your environment, which remains a top priority at Google.\nThank you for choosing Google Cloud.\n\nApparently they decided it was way to dangerous to let me deal with the issue on my own, instead, whenever they find an API key in the wild, they'll just disable the key automatically. That makes perfect sense (I'm being serious here, just in case you think otherwise), protecting me from myself. If they'd taken that approach last year when they discovered my little issue, they would have shut down that feature of this site and forced me to take corrective action sooner.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Cloud Development"
  
  ]
  },

  {
  "title": "Microsoft Sunsets Visual Studio App Center",
  "date":"Tue Mar 19 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1710892800,
  "url":"/posts/2024/microsoft-sunsets-app-center/",
  "content":"Back in 2017, I had an opportunity to work on the Visual Studio documentation as a contractor. I was trying to find full time work, but jumped at the opportunity to write some docs for Visual Studio. I wrote/updated most of the docs for Visual Studio Tools for Apache Cordova (TACO) and since I had multiple books under my belt about Apache Cordova, I was a perfect fit.\nIt was supposed to be a contract to hire opportunity, but that didn't work out so I went and did something else for a while. A few months later, I found an opportunity on the Visual Studio App Center (https://visualstudio.microsoft.com/app-center/) team. App Center was Mobile DevOps in the cloud and it was an amazing product. You can read about the launch here.\nOne of the most important and interesting (for me anyway) parts of App Center was CodePush, a platform that allowed over the air (OTA) updates to Cordova and React Native applications.\nI worked on a few things on the App Center team, I was involved in researching and planning for the Mobile Backend as a Service (MBaaS) capabilities in the platform and I ended up as Program Manager for the Visual Studio App Center Push service as well as Azure Notification Hubs (both ran on the same infrastructure).\nUltimately, what happened to App Center was GitHub. The App Center team at Microsoft was part of the Azure DevOps division, and when Microsoft moved most of the Azure DevOps team to GitHub, Visual Studio App Center became an orphan. GitHub didn't know what to do with App Center, so they put it on maintenance with a very small development team and let it languish for many years.\nI made a lot of great friends working on App Center, most parted ways from Microsoft (me included) long ago. Fortunately, my experience on the App Center team led to Oracle recruiting me for a Product Manager job at Oracle Cloud Infrastructure (OCI), so it all worked out.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Cloud Development"
  
  ]
  },

  {
  "title": "Generating Eleventy Post Descriptions Using Generative AI",
  "date":"Sun Mar 17 2024 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1710720000,
  "url":"/posts/2024/generating-post-descriptions/",
  "content":"When I migrated this site from Joomla to Eleventy, I added a description field to the site's standard post template:\n\nWith that in place, I modified the home page and the Articles page to display the contents of the post's description field if it was populated. If it's not populated, the site pulls the first paragraph of the article using some highly modified code I pulled from Raymond Camden's site.\nI've been working in the Generative AI (GenAI) space for a few months now, and one of the things I wanted to do was use GenAI to populate post descriptions for me. I thought about building something that generated descriptions for the site's posts during the build process, but sometimes the first paragraph was good enough, so there's a lot of posts in this site that don't have a description populated. Yes, I know, I could build something that only generated descriptions for newer posts, but that wouldn't work for me for the same reason: I don't assign descriptions to all posts on this site.\nIf you remember back to last year, I published an article called Visual Studio Code Progress Cancelled by Async Task where I showed how to do something I thought was cool in a Visual Studio Code extension. I wrote that because I always wanted to publish a Visual Studio Code extension, and I'd started playing around with doing so. The end result is that I created a new Visual Studio Code extension called Describer GenAI that I published to the Visual Studio Code Marketplace a few weeks back.\nThe extension uses ChatGPT to generate a description of an article/post file being edited in Visual Studio Code.\nTo use the extension, the only requirements are:\n\nYou must have a ChatGPT API key\nThe article/post file being edited must have YAML front matter as shown at the beginning of the article.\n\nWhen you invoke the extension's generate command, the extension:\n\nValidates that the extension was configured with a ChatGPT API key.\nChecks to make sure the file being edited has YAML front matter.\nGrabs the article content (excluding the front matter) and sends it to ChatGPT with a prompt that asks it to generate a brief description of the article.\nWhen the response comes back from the ChatGPT API, the extension adds the description to the post's front matter description property (configurable, see below).\n\nNow, I'm not an expert in GenAI prompt Engineering, but I was able to get good enough results using the following prompt:\n\nWith the article content delimited with triple double quote marks &quot;&quot;&quot;${genText}&quot;&quot;&quot;, generate a concise summary of the article using first-person perspective as if I am summarizing it myself\n\nIn this case, genText contains the content of the article (again, minus the front matter).\nNote: If someone wants to suggest a better version of this, please let me know.\nInstallation\nThe extension installs just like any other Visual Studio Code extension, simply search for it using 'describer' and you should be able to find it easily.\nConfiguration\nYou must configure the extension before you can use it. To open the extension's configuration settings, open the Visual Studio Code Command Palette and select Open Describer Settings as shown in the figure below:\n\nVisual Studio Code will open the settings panel for the extension as shown in the figure below:\n\nThe following table describes each of the configuration options.\n\n\n\nName\nDescription\n\n\n\n\nAPI Key\nA valid ChatGPT API key.\n\n\nEnable Generated Flag\nWhen enabled, adds a generatedDescription property to the file's front matter and sets the value to true. I used this to display different content in the site when I'm showing a generated description instead of one I wrote myself. In this site's case, it adds 'AI generated' before the description.\n\n\nTarget Property\nBy default, the extension saves the generated description to the file's description front matter property. If you would like the extension to save the generated description to a different front matter property, enter the name of the property in this field.\n\n\n\nUsage\nOnce you configured the extension with an API key, to generate a description of an article, right click in the article content and select Generate Description as shown in the following figure:\n\nThe extension will spin for a few seconds, then update the front matter with a description as shown in the following example:\n\nThat's all there is to it and it works pretty well. Sometimes ChatGPT forgets that I want the description generated from a first person perspective as shown in the example above. To get a better description, just run the generation process again and you'll get something different:\n\nUsing generatedDescription\nNotice the generatedDescription property. With that in place, I show a text pill in article lists that says 'AI Generated' using the following code:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Artificial Intelligence"
  
  ]
  },

  {
  "title": "FedEx Foibles",
  "date":"Thu Mar 07 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1709856000,
  "url":"/posts/2024/fedex-foibles/",
  "content":"I noticed lately that FedEx seems incapable of knowing where packages are in their delivery network. As an example, take a look at the following screen shot taken this morning:\n\nThis particular package shipped on March first from Strongsville, OH. It traveled through FedEx's shipping network to Charlotte (where I live), arriving in the delivery city the next day (Saturday, March 2nd). The package sat there for a few days, in the delivery city mind you, before FedEx shipped it to a small town outside of Charleston SC. Then it made its way to Spartanburg, back to Charlotte and was supposed to be delivered but never made it on the truck.\nThat little package had quite a trip across the Carolinas.\nSo it was out for delivery yesterday and its supposedly out for delivery yet again today, but look at the scheduled delivery date. Even though it's out for delivery today, FedEx expects that it will somehow not deliver until tomorrow?\nWTF?\nI thought FedEx was the tightest ship in the shipping business? What happened to their IT capabilities that it no longer knows where to take packages and when it can deliver them?\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "The Pace of AI Advancement",
  "date":"Thu Feb 29 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1709251200,
  "url":"/posts/2024/pace-ai-advancement/",
  "content":"Many years ago I authored my last book. It was 2020, and the book came out right at the beginning, or near the beginning, of the Global Pandemic. The book was my first book published in color and it was short and right on point for the selected topic. I thought it was a really good book, but, sadly, it didn't sell.\nIts possible that everyone was busy dealing with staying home and didn't buy any books, but I'm not sure that I believe that. I think the book released at a time when readers transitioned from reading books to watching video courses. At the time too, with everyone staying home, a lot of writers like me started using their spare time to publish technical articles on a variety of topics. Learners could find almost anything online and books were just not part of it apparently.\nAnother reason for limited book publishing was that technology advanced so quickly that there was limited opportunity to publish a useful book on a topic before the book quickly becomes obsolete. With my publisher, I wrote several books in less time that it took them to actually publish the book. With my work on the Apache Cordova series, major versions started coming out more rapidly than any book author or audience could keep up.\nAppropriately, my publisher transitioned to online courses and videos. Every book topic I proposed was shut down by the publisher; I desperately wanted to write a book on Flutter, but even though Flutter was very popular (I LOVE working in Flutter even though I Don't Know Dart), nobody wanted a book on it.\nFast forward to today and, as I expect, most of us are somehow involved in AI. If the pace of technology 4 years ago was fast, I can't even think of how to quantify the pace of AI Advancement against it. it has to be 10 or 100 times faster.\nI'm working with a team building a Generative AI (GenAI) based service in OCI and there were a very simple set of capabilities planned for the initial release. However, with the advancement in all the AI-based tooling in use, the team had to stop development and refactor their plans so that when they shipped the product offering would be relevant. With this refactor and just a couple of extra months, they will be able to deliver a much more robust set of features. The roadmaps for these types of products are big, but none of them are stable because the available capabilities change (grow, enhance) way too rapidly.\nIts an exciting but also scary time to be in the space, but I honestly don't know how I'll be able to keep up and still do my day job.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Artificial Intelligence"
  
  ]
  },

  {
  "title": "Bogus Wells SMS",
  "date":"Thu Feb 22 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1708646400,
  "url":"/posts/2024/bogus-wells-sms/",
  "content":"I got a spam, malware, phishing text message today that said it was from Wells Fargo but I knew better. After looking at it for a couple of seconds, I had to laugh then write about it. Here's the message I received:\n\nFirst of all, I'm not a Wells Fargo customer so that was my first clue that this was a phishing message or something.\nNext, I looked at the phone number: +1 141 020 0504\nThe last time I checked, 141 isn't a US area code. From what I remember, area codes can't begin with a 0 or a 1. Neither is 020 a valid NNX. From NANPA, the first reference I found using Google:\n\nA Central Office (CO) code or NXX code refers to the second three digits (also called digits D-E-F) of a ten-digit telephone number in the form of NPA-NXX-XXXX, where N represents any one of the numbers 2 through 9 and X represents any one of the numbers 0 through 9.\n\nSo why would Wells Fargo send me a text message about 'my account' from outside the country? Yeah, they wouldn't.\nWhat made me laugh was that it was apparently from Wells Farqo (that's a Q instead of the G in Wells Fargo) but the transaction amount had a dollar sign with some interesting character choices in it: $/416,63. I'm not sure what the / is for, that's not part of a currency value in the US. But the comma for a decimal separator was the funniest part as we use periods, not commas, to separate dollars and cents.\nThis just proves that all you have to do is look just for a few seconds to identify spam or dangerous messages. When you can clearly see it's not a US phone number nor is it an American formatted currency amount, it's time to report the message to your phone company.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "New Post Skipping Category Prompt",
  "date":"Sat Feb 10 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1707609600,
  "url":"/posts/2024/new-post-skipping-category-prompt/",
  "content":"After my most recent post I realized I needed another enhancement to my Eleventy New Post utility.\nStill working in the Eleventy-based docs site, I realized that I wouldn't use Categories on that site like I do on others. For this site, I'm hard coding navigation and there's no reason to arbitrarily group posts in that case. Anyway, the new version is up there, please let me know what you think about it and if you have any feature suggestions.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Added Folder Selection My New Post Utility",
  "date":"Mon Feb 05 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1707177600,
  "url":"/posts/2024/added-folder-selection-new-post/",
  "content":"I started working on an Eleventy-based documentation site recently and noticed an issue with my Eleventy New Post. For this site, I planned to use a separate folder under src/posts for each product being documented on the site. When creating a new post using the utility, I wanted to select the target folder as part of the new post creation process like this:\n\nWith this modification, you can select the posts folder (controlled through a configuration setting for the utility) or any of the sub-folders underneath the posts folder as shown in the example.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Node.js"
  
  ]
  },

  {
  "title": "GenAI Recruiter Spam",
  "date":"Fri Jan 26 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1706313600,
  "url":"/posts/2024/genai-recruiter-spam/",
  "content":"\nThis post copied from my World Without Apps site.\n\nI received an email the other day at work from what looked like a recruiter offering to help me find a job. I was more than a little stunned at the audacity of the recruiter to send me an email to my work email address. The more I thought about it, the more I realized that a recruiter wouldn't email me at work. They all connect with me through LinkedIn.\nAs I read through the email, I said to myself &quot;wait a minute, this wasn't written by a person&quot;. Here, take a look at the email content:\n\nAs I saw it, someone used Generative AI (GenAI) to generate a profile based on my resume or perhaps a job application I filled out years ago. Again, I simply couldn't believe the audacity of this approach.\nAs I scrolled down the email, below the recommended positions based on this generated profile, I saw surprisingly honest attestation that the recruiter, Jenny Johnson, was an AI representative.\n\nCan you imagine the profit generation aspect of this?\n\nScour the Internet for resumes\nGenerate a profile for each\nScour the Internet for job postings\nUse GenAI to match job openings for each profile\nSend everything to an email for the target human.\n\nSomeone can do this all day every day without needing any staff. For any human that gets an email clicks on a link to submit an application, the AI team gets a referral fee for any hires. It's genius - you can do this with one guy (or gal) and pay for some cloud compute and email services and you're all set. Simply mind boggling.\nIf you happen to not get an unsolicited email, all you have to do is find the site, fill in a couple of information items and enter the process. If you're looking for a job and find a job, it's the easiest thing for you ever. Here's the site, Job Title, skills and location are all it needs to use AI to find potentially hundreds or thousands of potential job openings that match.\n\nAnd this is an excellent example of what happens in the World Without Apps.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Delphi Passing Data Between Forms",
  "date":"Sun Jan 21 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1705881600,
  "url":"/posts/2024/delphi-pass-data-between-forms/",
  "content":"I'm building a Windows application using Delphi and I needed the ability to access data on the main form from another form (a form invoked by the main form). I poked around on the Internet and found different ways to do it.\nI assume the Embarcadero web site has knowledge base articles on how to do this, but they apparently had hardware failures in their data center (who has their own data center anymore?) so most of their sites are down and have been for most of a week.\nMy Research\nThe first example I found showed how to pass a data object when creating a form, then accessing that passed data object in the target form. I couldn't get it to work, but to be honest I didn't spend too much time trying.\nBack to Stack Overflow, I found a question posted called Delphi - passing variables to another form (without global variables). This article explains that I could create the target form, then set VCL component properties in the target form using data from the source form. That looked like a truly elegant solution and I immediately tried it out in my app. On the surface, this looked like a great solution. However, what the author failed to mention is that once you set those properties on the target form, any time you try to access the passed data from code on the target form the application crashes with an access violation. You can apparently use the data in a component (like a drop-down field or a text box) and change the value in it from the form, but as soon as I accessed the data in code, the app crashed.\nFor my particular application, what I'm trying to pass to the target form is a String List (TStringList) that I intend to access in code on the target form to manipulate the data (in this case, I'm generating a report from the data and saving it to file).\nAlright, back to Stack Overflow (again) and it looks like I'm going to have to create a Global data value for my string list and access it everywhere in my app.\nYes, I know that Delphi creates a Global variable for the main form in a Delphi application (and other forms too automatically); I've been a Delphi developer since v1 and a Turbo Pascal developer since the mid 80's. I can easily reference components on the source form from the target form's code. But that tightly couples the forms and even though I know now that the source form's data will always be available, I just don't like that approach. Having a globals file helps organize things as it's really easy to tell what's a global and what isn't when all globals are in the same file.\nWhat I saw next on Stack Overflow suggested making a separate globals unit and use that unit wherever I needed.  Ok, that works for me and I can easily add other data values to it so I set about implementing it.\nCreating a Globals Unit\nWhen I added a globals unit to the application, the IDE generated this:\n\nI know how to use this when I'm working with a form, but how do I build global data values in this thing? None of the articles I found showed me how, and of course the Embarcadero web sites are down.\nLets use my string list as an example. I know I want to expose my list to other parts of the app, so I need to put my variable declaration in the interface section.\n\nBut that doesn't work because TStringList is part of the System.Classes unit and this unit doesn't have a reference to it.  That code as I showed above won't compile.\nI'm used to adding uses clause to the implementation section, but just for grins I moved what I needed to the interface section and it worked:\n\nAlright, my string list is defined, but it's not an Integer or String that I can use without initializing, so I have to find a way to Create the resource in the unit.\nNot included in the generated unit file is an initialization section that I quickly added to the file:\n\nWith this in place, when the unit loads, it initializes the variable so it can be easily used by any part of the app that loads the unit.\nBeing an experienced Windows/Delphi developer, I know that I could get away with not disposing of my global variable when I'm done with it. Theoretically the app would clean up the allocated memory automatically when I close the application. Just to make sure though, I used the finalization option in the unit file to free up the variable:\n\nWhen the app closes, Delphi calls the finalization code for every unit and the app releases the memory allocated for myStringList.\nWith this in place, everything worked as expected. I loaded the globals unit in each form's uses clause and it worked like a champ. Here's the complete globals unit code:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Windows Path Viewer App",
  "date":"Sat Jan 20 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1705795200,
  "url":"/posts/2024/windows-path-viewer-app/",
  "content":"A while back I had a problem with my Windows Path that I wrote about in Windows Path Items Not Available in Visual Studio Code. I was thinking about that problem recently and decided to build my own tooling for managing my system path. I didn't do this because I needed to, but I wanted to write some Windows code (Using Delphi) and this topic is interesting.\nAs I was playing around with the code, I ran into an issue that I simply couldn't figure out. It turned out to be a Stupid User Problem (me), you can read about it here: Delphi Read Windows 11 System Path. Anyway, in order to ask that question, I needed to build a sample app that demonstrated the problem. My current project  has a lot of other code in it and I use some VCL components many other people won't have, so I decided to build a limited scope sample application and share the link to that project in the Stack Overflow question.\nWindows stores the User Path in HKEY_CURRENT_USER\\Environment and the System Path in HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment, so the code has to pull the values from different parts of the Registry.\nWindows stores the path as a string, so to display it in the Listboxes, the app splits the string into an array using:\n\nThe Code\nHere's the core of the application's code.\n\nHere's a screen shot of the application:\n\nChanging the Path\nThe application opens the Registry for read-only access, so it can't make any changes to the Path (or any other part of the registry for that matter). In order to make changes to the Path values, you must do three things.\nFirst, in your code, you must open the Registry for write access:\n\nNext, you must run the application with Administrator access. This is because an everyday Windows user doesn't have access to modify the System Path. Users can modify their User path all day long, but as soon as you try to change the System Path, the app will crash. To enable admin mode in the Delphi IDE, open Projects -&gt; Options and select the Manifest section. Set Execution Level to Require Administrator and save your changes.\n\nFinally, you must run Delphi with administrator privileges, otherwise you won't be able to test write access to the System Path. If you forget to do this and you launch a project that requires administrator access, Delphi will display an error indicating &quot;The requested operation requires elevation.&quot;\n\nSource Code\nI published all the code into a stand-alone Delphi app called Windows Path Viewer Delphi\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Added Monthly Posts Heatmap To The Site",
  "date":"Sun Jan 14 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1705276800,
  "url":"/posts/2024/added-monthly-posts-heatmap/",
  "content":"I added a Posts per Month array to the Eleventy Post Stats plugin today. This allowed me to add a posts per month heatmap to the site's Statistics page. Its fun to see where I was busy on the site and when I published nothing.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Zinio Ridiculous Delete Account Process",
  "date":"Fri Jan 12 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1705104000,
  "url":"/posts/2024/zinio-delete-account/",
  "content":"I created a Zinio account many years ago (many, many years ago). Online magazines was a thing then and there were a couple of magazines I was interested in that had moved to the platform. I stopped reading those magazines years ago and completely forgot about my account.\nI was bored the other day and I was poking around on my tablet. I suddenly remembered my Zinio account and opened the browser to see if it was still a thing. I found it, logged in, and browsed all of my magazines (going back into the early 2000's).  None of that interested me anymore and I'm not interested in reading magazines online, so I looked for the link or button to delete my account. I quickly found it and clicked it, but what happened next was just ridiculous.\nA few minutes later, I received an email from them acknowledging the deletion request:\n\nWe have received delete me request for the following user Email: john@myemail.com, User ID: some_long_account_id. Please follow the legal process to confirm receipt of this request and follow the legal delete me process as required by the law. FYI this needs to be actioned by the Data Controller and Data Processor.\n\nLegal process? What legal process? Data Controller? Data Processor?  I know what those things are, but how exactly do they apply here?  Zinio is the data controller, wherever they host their application platform is the data processor. I'm not involved in either.\nA short while later, I received another email from them:\n\nHello,\nWe acknowledge receipt of your request for deletion of personal data on 2024-01-10,and will provide you a formal response to your request as soon as commercially possible, but in any event within the time established by applicable law.\nPlease take note that we cannot process data privacy requests or provide any personal data if we cannot verify both the identity and authority of the individual submitting such request. In some cases, we may request proof of identity to process a request including, without limitation: (i) if you send us the request from an email address that is different than the one you are enquiring about; (ii) if you send us the request from an email address that is different from the one you use in connection with your account or relationship with us; (iii) if we store more personal data than an email address for you and such request relates to or impacts such additional personal data, or (iv) if you provide us with data that does not match the personal data in our records. We will only use personal data provided in a verifiable data privacy request to verify the requestor's identity or authority to make the request.\nPlease be advised that, once processed, the deletion or erasure of personal data is permanent and you will loose access to your account, including any relevant orders, purchased magazines and subscriptions. No refunds or other accommodations shall be made with respect to any loss of access or functionality to an account or any purchased products or services resulting from the processing of a data privacy request.\nBest Regards\nZinio Security Team\n*PLEASE NOTE: In addition to its own Newsstand and mobile applications, ZINIO serves as delivery agent for digital magazine content for over 800 publishers. In the event that you place an order for a digital magazine directly with a publisher after the completion of your personal data deletion request, this may result in a new ZINIO account being automatically created for you to facilitate delivery of such content. We encourage you to contact publishers directly to understand how their digital magazines will be delivered.\nPlease feel free to contact us for further assistance.\nThanks and regards,\nJanet K\n\nHoly crap, seriously? Dude, all I'm trying to do is delete an account I haven't used in almost a decade.\nI logged into my Zinio account using my Zinio account credentials and followed the process to request an account deletion. Why are you emailing me about legal issues? Just do it and be done with it.\nI didn't make a request for deletion of personal data, all I asked you to do is delete my account. If you want to hang onto the data after you delete the account, I truly don't care.  Well, that's not true - I do care if they leak my data, but I don't care if they want to keep it around at their expense.\nNope, they weren't done yet.\n\nDear John,\nAs a follow-up to your data privacy request, we have confirmed that your request for deletion of personal data meets the requirements of applicable data protection laws. Further, please be advised that we have proceeded to complete your request and the deletion of the following personal data linked to your account: john@myemail.com.\nPlease note, however, that it may take up to seven (7) days for the personal data subject to your request to be removed from all affected systems.\nAlthough the processing of your deletion request permanently removes the impacted data from the majority of the databases and records we maintain, certain portions of perso",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Package Could Not Be Delivered Spam",
  "date":"Thu Jan 11 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1705017600,
  "url":"/posts/2024/spam-package-could-not-be-delivered/",
  "content":"It's been a long time since I've torn apart a spam message here. My daughter sent me a screen shot of a text message she received yesterday (supposedly from the United States Postal Service (USPS) and I thought I'd share the screen shot and debunk it.\nHere's the text of the message my daughter received:\n\nPackage Tracking: Your package arrived at the transit center but could not be delivered due to incomplete address information.\n\nHere's the screenshot:\n\nI received a bunch of these over the last few months, but surprisingly every one of them was sent from a non-US telephone number (I didn't keep track, but I think the sender primarily used a 46 country code (Sweden)). It was pretty easy to ignore the messages once I noticed that, but I wonder how many people fell for it anyway. I imagine that most Americans don't get a lot of phone calls from outside of North America, so I bet they thought the 46 at the start of the number was a system number or something like that.\nAnyway, for this piece of spam or phishing my daughter received, the text message came from a US telephone number (Washington state) so at least these criminals finally figured that part out.\nLooking at the message, I was able to give my daughter the following advice:\n\nThe US Postal Service isn't going to end a text message with &quot;best regards,&quot; in it.\nI'm pretty sure that USPS Customer Service doesn't send text messages anyway. As a side note, does the USPS really care about customer service? :-)\nThe USPS likely doesn't have her phone number.\nWhat are the chances the post office has her phone number but NOT her correct delivery address?\n\nAnother thing about this message struck me as odd, the URL pointing to https://cutt.ly. I'd never heard of that domain, so I fired up a linux box and accessed it and learned two things:\n\nhttps://cutt.ly is a link shortener that I'd never heard of before.\nThe shortened URL had been deleted.\n\nSo, even if my daughter had clicked on the URL, nothing would have happened. I assume someone complained and they pulled the nefarious link from their site. You can't always count on that though.\nSome good news here is that as far as I know, links you get in text messages can't be hidden behind another URL (which is something you can do in emails and web pages).\nI'm also lucky that I have an extra linux system here I can fire up to do unsafe things (then quickly tear down when I'm done). I've also tested spam and fishing URLs in a virtual machine in the past as well.\nI assume that the postal service isn't going to use a third-party link shortener. At the volume of text messages the postal service likely sends, they're not going to use a third-party URL shortener service because that would cost them a lot of money.\nI hope this helps you recognize spam or phishing texts more easily.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Phishing"
  
  ]
  },

  {
  "title": "Updated Eleventy Future Post Plugin",
  "date":"Wed Jan 10 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1704931200,
  "url":"/posts/2024/updated-eleventy-future-post-plugin/",
  "content":"In yesterday's post, I announced my Future Post plugin for Eleventy and mentioned that I didn't configure the plugin so it would render posts with a future date when testing the site. Since then I found some time to look at the implementation for that and decided to go ahead and add it to version 0.0.2 which I published today.\nThe Eleventy Base Blog does something weird with a environment variable to implement this and I wanted to make my code cleaner.\nIn the plugin's code, I added a new Boolean variable called isServing:\n\nNext, as the Eleventy Base Blog does, I added a before event handler where the plugin can access the runMode and set the isServing variable. This allows that check between the two options (serve and watch as shown below) to happen only once, at the start of the Eleventy build process, and should help improve overall performance.\n\nFinally, I updated the addGlobalData method to skip the date check when isServing is true:\n\nThis approach eliminates the date comparison while serving the site which should improve performance while testing.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Hiding Future Posts in Eleventy",
  "date":"Tue Jan 09 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1704844800,
  "url":"/posts/2024/hiding-future-posts-eleventy/",
  "content":"I often start articles on this site before I'm ready to publish them, especially if they're long articles. I needed a solution that allows me to create the post/article, but not publish it until I was ready.\nThe Eleventy Base Blog project has a drafts feather that allows you to work on a post within an Eleventy project without publishing it. You essentially assign a draft state to the post and Eleventy doesn't publish it during the build process until you remove the draft state.\nFor my use case, I wanted something different, I didn't want to manage the state of the document, I wanted the document to publish based on metadata in the post (the post's date property). The Joomla CMS has this feature, you simply set the publish date and time in the post and it miraculously appears at the selected date and time. WordPress allows you to do both, set a published state and a date to publish it.\nI had some time this week to look at the code behind the base blog's draft feature and noticed it would be pretty easy to modify it to suit my needs. Here's the relevant code from the base blog's eleventy.config.drafts.js file:\n\nThe code uses eleventyExcludeFromCollections to decide whether to publish the post or not. A simple check for draft state (and whether the environment says to build drafts) and the post is built or not built based on it.\nTweaking this to only publish the post if the post date is before the current date/time looks like this:\n\nLooking at the code, I realized I was calculating the current time every time the Eleventy build process calls the function, so refactoring the code so its tighter (and slightly faster) looks like this:\n\nThis code effectively returns true (meaning to exclude the doc from the build process) for any post with a date after the current date. Otherwise it returns data.eleventyExcludeFromCollections which is, I think, the current state from any other Global Data functions configured in the Eleventy project (meaning that some other process can mark the post for exclusion as well).\nThat solution works, but there's one issue I encountered when I tested the code. Eleventy assumes that post date (data.page.date) is in Coordinated Universal Time (UTC) but the code's call to new Date() returns a local date. So, in order to do the date/time difference math correctly, both dates (current date and post date) have to be in the same time zone.\nI tried getting the current date (currentDate) variable rendered in UTC, but everything I tried failed for one reason or another. Instead, I decided to use JavaScript's getTimezoneOffset method to convert the page date correctly for me. The code below takes that into account, converting the page date to the same date (which is what matters) but at at midnight (00:00:00) in the current time zone.\n\nThe math works, Eleventy generates any post published before or on the build date, for any future posts nothing happens and they're omitted from the site. When the publish date comes around, you simply perform a build and you're all set. With the Base Blog's drafts capability, you must change the state of the post (remove the drafts status) then publish the site.\nThe Eleventy Base Blog uses the execution mode to control whether to generate drafts or not. Using the code below generates drafts when in development mode but omits them during the build process only (no serve).\n\nThis allows you to view drafts while you're editing them. I could have adopted this approach here as well, but for my particular use case, I don't need to see posts in the site as I write them. I can always test them locally before I publish them on the target date.\nPlugin\nI created a plugin for this called Eleventy Plugin Future Post so both of us can add this functionality to our sites without manually copying around the .js file. The project contains sample documents and a simple index.html file you can use to test out the plugin. Just clone the project, install packages and build the site.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Google Cloud Multiple Functions in a Project",
  "date":"Sun Jan 07 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1704672000,
  "url":"/posts/2024/google-cloud-multiple-functions/",
  "content":"In my previous post Coding Google Functions Using TypeScript I showed how to code Google Functions using TypeScript. Something else I wanted for my Google Cloud Functions project was to be able to manage multiple functions in a single GitHub project. This post describes how to do it.\nCloud Function Weirdness\nOne of the things that really surprises me about many of the Cloud Functions offerings is that the cloud providers design their solutions so that every function is treated separately by the cloud.  For example, OCI based their Functions offering on the fn project which creates and deploys a separate docker container for each function.\nIn Google Cloud Functions, I don't know what the underpinnings are, but they treat each function separately as well. To create a function, you login to the Google Cloud console, navigate to your Functions project, then click Create to make a new function. Once the console creates the function, you must download the function's code as a zip file and extract it to your local development system in a separate folder for each function.\nThe first Cloud Functions environment I worked in was Firebase and Firebase takes a completely different approach. Firebase allows you to create a single Functions project then code multiple functions in the same project. They even provide multiple ways to structure your functions in the project.\nYou can have one big JavaScript or TypeScript file with multiple functions in it, or you can create multiple code files then expose all of the functions in a single project.  Here's an example from part of a Firebase Functions project I created years ago:\n\nThat's the root index.ts file for the Firebase Functions project and it loads other modules in my project and exposes them all through a single functions portal in the console. I was able to manage my code in multiple TypeScript files, but publish them a single collections of Functions.\nIt just makes no sense to me to force developers to treat each function as a separate project folder. Especially when it comes to deploying the functions, you must execute the cloud platform's CLI deploy command individually for each functions folder. If I was an Enterprise developer building a huge app, I'd be pulling out what's left of my hair dealing with this ridiculousness.\nMultiple Google Cloud Functions in a Project\nSo, back to my Google Cloud Functions (GCF) project.\nMy site uses three cloud functions, two that deal with Google Analytics and another that pulls in my GoodReads feed.\nNote: I didn't need my Goodreads feed deployed as a cloud function, but putting it there let me easily share the code across multiple projects.\nI followed the process to create each of the functions in the Google Cloud console. With the new functions deployed, I downloaded the source code zip files for each function into a single folder. From here, I extracted each function's code into a separate folder with the function name as the folder name.\n\nI made the whole folder (containing the different Functions folders) into a git repository and published the project to GitHub. In Visual Studio code, I navigate to each folder using the terminal to code, test, and deploy each function individually. This is slightly annoying, but at least I have everything in one GitHub project so I can easily work on my functions project on different development systems.\nAutomating Deployment of Multiple Google Cloud Functions\nWhat I needed though was a way to publish all of my functions together with one command. The Firebase CLI offers this, but the Google Cloud CLI does not. I could work on each function until they were all tested and ready to go, then execute this one command to publish all of them.\nWell, if you remember a while back I presented a session at All Things Open 2023 about Google's zx. I also published a post here about it called ## zx for Simplified Node Process Spawning. I knew that I could use zx to create a cross-platform script for automating the deployment process for all of my project's functions.\nI quickly created a zx script called deploy.mjs; here's the code:\n\nI started by hardcoding an array with the names of each of my project's functions, but then it occurred to me I could just build the array dynamically from the folder names in the project folder. That's what the first part of the code does, build out that function list:\n\nThe only hitch was that I had to skip the .git folder, but GitHub Copilot added that code for me automatically. Thinking about it, I should probably just ignore any folder that starts with a period; perhaps I'll make that change in the future.\nWith the folder/function list in hand, the code next loops through the functionList array and:\n\nChanges the current directory to the function folder (using the name of the function as the folder name)\nExecutes the Google Cloud Platform CLI deploy command for the function\nChanges the current directory back to the project folder (..).\n\nHere's the code that handles that par",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Cloud Development",
  
    "JavaScript",
  
    "Node.js"
  
  ]
  },

  {
  "title": "Coding Google Functions Using TypeScript",
  "date":"Sat Jan 06 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1704585600,
  "url":"/posts/2024/google-cloud-functions-typescript/",
  "content":"As I mentioned in my previous post, I migrated some functionality from this site to Google Cloud Functions due to some security issues related to how I implemented the code. Moving the code from the public repo for this site to a private repo containing Google Cloud Functions allows me to do what I need to do without exposing secrets.\nI know everyone doesn't agree with me on this, but I code in TypeScript when I can. I understand why Microsoft created TypeScript and I understand the value of what it offers. I also get tremendous benefit from coding in TypeScript over JavaScript and I have yet to run into any long build processes due to my use of TypeScript.\nSadly, when you search the Internet for documentation on how to configure Google Cloud Functions using TypeScript, no official documentation from Google appears. That's not necessarily surprising as it's not that hard to setup, but interesting that Google Firebase (through the Firebase CLI) will setup a functions project for you automatically for you. Sadly, when I googled &quot;google functions typescript&quot;, most of the articles that appeared in the results talked about Firebase. Sigh.\nWhen I started coding my functions last week, I found few article that describes the process; the one I used was: Cloud Functions with TypeScript. I mention that article because there were some topics not described very well in the article, and I wanted to do a better job here. It was also written several years ago, so things have likely changed since then.\nConfiguring The Project\nAlright, as far as I can tell, there's no way to create a Google Cloud Function (I'm going to call it GCF from here on) on your local system then publish or deploy it to the cloud. So, to get started:\n\nCreate the JavaScript/Node function you want in GCF\nDownload the function's zip file from GCF to your local development environment\nExtract the downloaded files to a folder on your hard drive.\n\nNote: In my next post, I'll demonstrate how to put multiple functions in a single project.\nThe new Function project has two files in it:\n\nindex.js - This contains the JavaScript code for your function. In our new TypeScript project, we're going to compile the TypeScript code into this JavaScript file for deployment to GCF.\npackage.json - The node.js configuration file for the function project.\n\nAt this point, the project's package.json file looks like this:\n\nCreate a new folder in the root of the project and call it src. This folder holds the TypeScript source code for the project. Create a file called index.ts in the folder and populate it with the following code:\n\nOpen a terminal window or command prompt and navigate to the folder with the extracted function files. I use the terminal in Visual Studio Code for this because I'm going to work in the editor after I'm done, so there's no need to open a dedicated terminal window for these simple steps. In the terminal window, execute the following command:\n\nWhen you're done, the file package.json file will look something like this:\n\nNext, in the terminal window, execute the following command:\n\nI have TypeScript installed globally on my system, so I accomplished the same thing using:\n\nThis adds a tsconfig.json file to the project that looks something like this:\n\nModify the tsconfig.json file so it looks like this:\n\nThe most important changes are these:\n\n&quot;rootDir&quot;: &quot;src&quot; - This tells the TypeScript compiler where to find the source files for the project.\n&quot;outDir&quot;: &quot;./&quot; - Tells the TypeScript compiler where to output the compiled files. A GCF project expects to fine the project's index.js file in the root of the project folder.\n&quot;include&quot;: [&quot;./src/**/*.ts&quot;], - This tells the TypeScript compiler which files to compile.\n&quot;exclude&quot;: [&quot;node_modules&quot;] - This tells the TypeScript compiler to ignore any TypeScript files in the node_modules folder. This probably isn't needed, but I put it in there anyway.\n\nFinally, we need to add the following scripts to the project's package.json file (I'll explain them in a minute):\n\nThe complete package.json file should look like this:\n\nHere's some details regarding the scripts:\nScript Details\n\n\n\nScript\nDescription\n\n\n\n\nbuild\nThe tsc command is the TypeScript compiler you'll use to compile the function's TypeScript code to JavaScript. I have TypeScript installed locally, so I can just type the tsc command in a project terminal window to compile the code. If you don't have that setup, and you probably shouldn't for some good reasons, compile your project's code by executing npm run build in a project terminal window. This compiles the TypeScript in src/index.ts to /index.js\n\n\ndeploy\nDeploying the function to GCF requires a complicated command that I can never remember the syntax of. Instead, I added it as a build script, so any time I want to deploy the function, I simply execute npm run deploy in a project terminal window. I describe this script in a later",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Cloud Development",
  
    "JavaScript",
  
    "Node.js"
  
  ]
  },

  {
  "title": "Leaked Credentials from Google Cloud Project",
  "date":"Fri Jan 05 2024 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1704499200,
  "url":"/posts/2024/google-cloud-support-notice/",
  "content":"When I migrated this site from Joomla to Eleventy, a couple of the features I added pulled data from Google Analytics (GA):\n\nThe site's Home page uses GA to pull in the 10 most popular posts.\nThe site's Statistics page uses GA to display some access statistics.\n\nFor the GA integration, I used instructions I found on fjolt.com. The article was pretty clear, so I was able to code the integration in no time. One issue though, was that the Google Analytics Data: Node.js Client uses an external credential file and that's where this story begins.\nThe Problem\nA few months after I launched the site, I received an email from Google Cloud Support complaining about Leaked Credentials. Here's the email content, cleaned up and sterilized:\n\nHello,\nCase Subject: Leaked Credentials from Google Cloud Project jmw-static-site\nWe have detected potentially compromised Service Account authentication credentials associated with the following Google Cloud Platform account: blahblahblah@jblah.iam.gserviceaccount.com with key ID  This key was found at the following URL: https://github.com/johnwargo/johnwargo-static-11ty.\nBased on our investigation of the issue, we believe that you or your organization may have inadvertently published the affected Service Account credentials in public sources or websites (for instance, if credentials were mistakenly uploaded to a service like GitHub). Immediate action is required to secure your account(s). We strongly recommend that you take the following steps: --- Log in to the Google Cloud Console (cloud.google.com/console) and review the activity on your account. -- Revoke all (or listed) credentials for compromised Service Accounts. As every resource accessible to the Service Account may have been affected, it is best to revoke and reissue all credentials on potentially affected projects.\nFor more details, review the instructions available at https://cloud.google.com/security/compromised-credentials ---Delete all unauthorized VMs or resources. ---Take immediate steps to ensure that your Service Account credentials are not embedded in public source code systems, stored in download directories, or unintentionally shared in other ways. The security of your Google Cloud Platform account(s) is important to us. You can find more information on securely using IAM at https://cloud.google.com/iam/docs/using-iam-securely and also recommend best practices for keeping service accounts keys safe at https://cloudplatform.googleblog.com/2017/07/help-keep-your-Google-Cloud-service-account-keys-safe.html. Please let us know if you have additional questions by responding to this message.\nPlease review your case and take any actions as requested. If you have any questions or require immediate assistance, please reply to this email to contact Google Cloud Support.\nYou can also view and comment on your case by logging into our support portal\nThanks for choosing Google Cloud Platform.\n—The Google Team\n\nNote: I was a little appalled at the format for the email, it was missing some punctuation and the whole email was one big blob of text. I added a bunch of carriage returns to the content above so it would be more easily readable.\nNow I know I probably shouldn't publish the key file in this site's public repository, but when I setup the key, I only gave it read access to my site's Analytics property so I didn't think that was a security risk.\nAnyway, I acknowledge it was a bit of a security risk, so I set about finding some way to eliminate the risk.\nResearch\nNow, I want the site's code to be publicly available. I'm not an Eleventy expert, but there's a lot of cool code in there and I wanted to be able to both write about it and let people access the source. Pulling the site's repo down (changing its visibility) wasn't an option.\nNext, I started playing around with using environment variables on my local system and my hosting project on Netlify and feed the key or key values into the code at build time. Unfortunately, the key object was too large to store in an environment variable. Playing around further, I tried to just store the key itself in an environment variable, but it was too long as well.\nI thought about putting the key in a cloud key vault, but after poking at a couple of them, I abandoned that approach because none of them allowed me to store an existing key in a vault. I even played around with storing the file in a cloud blob storage account and pulling it down during the build process. I tried it on Azure, but struggled to find a simple way to keep the key file secure but still access it using a public URL. I used to be a Product Manager for an Azure service, so I thought I knew it pretty well, but after hours of searching for a solution I simply gave up. The docs are just not useful.\nResolution\nI finally gave up last week and pulled all of the offending code out of the public repo and migrated all of it to a Cloud Functions project.\nI tried first to do it in Firebase Functions (FF); I like FF because it",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Cloud Development",
  
    "Eleventy",
  
    "Web Development"
  
  ]
  },

  {
  "title": "Launching a Windows Terminal to a Specific Folder",
  "date":"Sun Dec 31 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1704067200,
  "url":"/posts/2024/launch-windows-terminal/",
  "content":"In Windows Path Items Not Available in Visual Studio Code I mentioned opening a command prompt or terminal window from Windows File Explorer but didn't explain what I meant. Years ago I learned an interesting trick for opening a Windows command prompt to a specific folder; there are two ways, but I don't think many people know about the second one. This article describes both options.\nRight-Click\nI think most people know about this one, but sharing just in case you don't. To open a command prompt/terminal window to a specific folder:\n\nOpen Windows File Explorer\nNavigate to the parent folder of the target folder (the folder you want to open a terminal window into)\nHold down the Shift key and hover the mouse over the target folder\nRight-click on the folder and select Open in Terminal as shown in the following figure\n\n\nAt this point, File Explorer opens the command prompt/terminal window to the scope of the selected folder as expected.\nCommand Approach\nAnother method for opening a terminal window to a particular folder, is to type the executable name for the terminal window (cmd) into the address bar in Windows File Explorer. Here's how to do it:\n\nOpen Windows File Explorer.\nNavigate to the target folder (the folder you want to open a terminal window into).\nIn the folder location input field highlighted in the following figure type cmd and press enter.\n\nSelecting the folder input field:\n\nEntering the command into the folder location input field:\n\nAt this point, File Explorer opens the terminal window to the scope of the selected folder as expected.\n\nNote: If you have the Windows Terminal App installed, which is different from the default command prompt application, you can also type wt instead of cmd to open the Windows Terminal app. With the Windows Terminal app installed either command opens the app.\nI hope this helps you use Windows more efficiently.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "End of the Year Wrap-up (2023)",
  "date":"Sat Dec 30 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703980800,
  "url":"/posts/2023/end-of-the-year-2023/",
  "content":"This was a big year for this site:\n\nI published 67 posts (the second most posts I published here in 14 years).\nLast year I only published 5 posts.\nThe previous 5 years I published 50 posts combined.\n\nYou can see the current stats on the Statistics page; with a end of year snapshot in the image below.\n\nOne of the reasons for so many posts was that I did a lot more coding this year and that generated a lot of articles I needed to write about the cool stuff I learned. I also migrated the site from Joomla! to Eleventy which was a lot of work and generated a lot of new learnings for me and new code I wrote that I could share with the world here.\nThis site today is everything I ever wanted for it. For many years I played around with a lot of different Content Management Systems (CMS) to use for this site and others, settling on Joomla! for this site's first 13 years. What I always wanted, and what I finally have with the Eleventy version of the site today, is the ability to add any feature I want to the site using code I wrote myself. I'm very happy and comfortable using plugins and other people's sample code in the site, but for Joomla I wasn't able to code my own features for the site because I didn't know PHP and didn't take the time to learn all the ins and outs of Joomla.\nWith Eleventy I have a complete understanding (well, almost complete) of the inner workings of the site and already coded a lot of unique features into the site. I even published three Eleventy plugins, so I hope I'm helping others create better Eleventy-based sites as well.\nI tried to pitch an Eleventy book to my publisher (I've already written 8 books) but I couldn't convince them. Fortunately, new Eleventy users have excellent Eleventy tutorials from people like Raymond Camden (I couldn't have built this site without help from Ray's site) and I learned a lot about Eleventy from Eleventy by Example: Create powerful, performant websites with a static-first strategy.\nWhat else happened this year?\n\nI had shoulder surgery (4 issues fixed) and recovered to almost 100% (without pain, surprisingly).\nOne of my children moved out of the house (one down, one more to go).\nI switched to a different team at Oracle (Oracle Cloud Infrastructure - OCI) and I'm much, much happier at work now.\nMy wife and I bought an electric car (Volkswagen ID.4) and we love it (except for the infotainment system which is complete shit).\nI read 69 books.\nI did some new Delphi software development this year, even released a new utility for Outlook: Outlook Windows Delete Empty Inbox Folders.\nI did a fair amount (but never enough) of Flutter development this year, I love that framework.\n\nWhat I have planned for next year?\nMore of the same, and more:\n\nRead at least 40 books; that's my typical yearly target.\nNo estimates on post count here, sorry.\nMore Flutter development (obviously).\nMore Delphi development (hopefully).\nLearn Astro.\nFinish that damn Sleeping Dragon in a Mailbox project.\n\nFor more than a year now I worked on a project for electronics hobbyists that I planned to kickstart on Kickstarter. I built something that really helps me when building a microcontroller-based project. I'll explain more as I get closer to launch, but part of this solution requires an injection molded part, so I'm kickstarting the expenses of having the mold made.\nAs part of this, I created a new company last year called Fumbly Stuff, LLC to manage the few products I created. My hope is that this becomes my retirement hobby business a few years from now.\nFinally, my goal is to learn Astro and deploy an updated e-commerce site for Fumbly Stuff for after the Kickstarter campaign completes.\nThank you for visiting my site and reading my posts. I hope you found something useful here!\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Updated My Eleventy New Post Module",
  "date":"Fri Dec 29 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703894400,
  "url":"/posts/2023/updated-eleventy-new-post/",
  "content":"When I published my Eleventy New Post package, it only supported selecting a single post category. That approach was fine for a while, but I noticed that I started assigning multiple categories to posts recently and the utility wasn't helping me as much as it could.\nI had some extra time on my hands today, so I decided to update the utility to allow selection of multiple categories. Here's an image of the updated version in action.\n\nLet me know if you find the utility useful.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Node.js"
  
  ]
  },

  {
  "title": "Eleventy GitHub Repositories Plugin",
  "date":"Tue Dec 26 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703635200,
  "url":"/posts/2023/eleventy-plugin-github-repositories/",
  "content":"As I wrote in Adding a GitHub Repository List to an Eleventy Site and Adding a GitHub Repository List to an Eleventy Site (part 2), I've been playing around with generating a GitHub repository list in an Eleventy site.\nBoth posts show how to do it with the first post demonstrating how to use unauthenticated access and the second authenticated access to the GitHub repos API. Both approaches required modifying the code and what I ultimately wanted was the ability to implement this capability as a plugin and therefore make it more easily configurable.\nI created a plugin, but I just couldn't get it to work and it seemed like Eleventy wasn't allowing me to call asynchronous code from a plugin. Well, it turned out that it was just developer stupidity (me) and after I had some success with the Eleventy File List Plugin I decided to go back and it and I figured it out.\nAnyway, I published the plugin today along with a demonstration Eleventy site (I love how easy it is to bundle an Eleventy Plugin and site into the same repository); it's available on GitHub at Eleventy Plugin GitHub Repositories and npm at eleventy-plugin-github-repos. I'll add both plugins to the Eleventy Plugin page before the end of the year.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Eleventy File List Plugin",
  "date":"Tue Dec 26 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703635200,
  "url":"/posts/2023/eleventy-plugin-file-list/",
  "content":"In the Joomla version of this site (the previous version of what you're looking at now) I used a downloads plugin which allowed me to view and manage site downloads from the admin panel. As I migrated to Eleventy I didn't migrate any of the existing downloads.\nWhen I presented at All Things Open this year, I added a download for the presentation slides to the site. Yes, I know I could host the file elsewhere, but I decided to host it here. As I sat around this week, with family gone and nothing to do, I decided to create a plugin that allowed me to list the downloads available on the site.\nTo install the plugin, open a terminal window or command prompt, navigate to an Eleventy project folder, and execute the following command:\n\nNext, in your Eleventy project's eleventy.config.js file, import the plugin as shown below:\n\nTo configure the plugin, you provide a folder location (relative to the Eleventy project's root folder)\n\nWith that in place, the plugin creates a Eleventy collection called fileList you can access from any page in the site.\nThe collection exposes an array containing the following file properties:\n\nname\nextension\npath\nfileSize: File size in bytes\ncreated: Create date\nmodified: Modified date\n\nThe plugin is available on GitHub at Eleventy Plugin File List and on npm at eleventy-plugin-file-list.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Execa Node Process Spawning",
  "date":"Mon Dec 25 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703548800,
  "url":"/posts/2023/execa-node-process-spawning/",
  "content":"At All Things Open session this year, I presented a session on some open source tools that simplify node.js process spawning. I intended to use my whole session to talk about zx (which I wrote about in zx for Simplified Node Process Spawning) but shortly after I learned about zx, I discovered a more mature alternative to zx called execa.\nThe purpose of this post is to share some of my thoughts on execa.\nBefore I start, here's a link to the session slide deck and Source Code.\nzx and execa both do essentially the same thing, provide a simplified wrapper around the node.js child_process capabilities. It's not hard to use child_process but there are extra things every developer has to do to use it (i.e. write additional code) which I'm not going to go into here.\nThe execa team took a slightly different approach than Google did with zx, but then quickly added similar functionality (the `$`` method zx uses). This means then that there can be very little difference between the two in action IMHO. To demonstrate this, I converted a script in created using zx to execa and only had to change two lines of code.\nzx uses the $ method to spawn external processes, to convert and existing zx script to use execa, all you have to do is load execa's version of $ using the following code:\n\nNext, replace any references in your existing script to zx's $ with $$ and you're done.\nzx automatically handles i/o, redirecting output to the console. execa doesn't, so without the const $$ = $({stdio: 'inherit'}); execa does everything silently. That was the biggest surprise to me, I'd run my script and everything seemed to work, but nothing showed up on the console.\nexeca allows node.js code to await completion of external processes, just like zx.\nIt was easier to install zx as a global module (npm install -g zx) and simply invoke zx to execute the script. execa needs that import statement, so it only seems to make sense to use it in node.js projects or a node.js based project like many web development projects.\nThere's really not a lot more for me to say here. If you look at the source code examples, you'll see that between the two modules they're both essentially the same except for the code changes mentioned above.\nI find that I don't need execa when I have zx in my back pocket. zx's execution environment allows me to code quick scripts and execute them anywhere where execa seems to tie me down to node.js based projects.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Node.js",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Adding a GitHub Repository List to an Eleventy Site (part 2)",
  "date":"Fri Dec 22 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703289600,
  "url":"/posts/2023/github-repository-list-eleventy-2/",
  "content":"In my previous post (Adding a GitHub Repository List to an Eleventy Site), I showed how to add a list of public repos to an Eleventy site using the GitHub REST API. In that post, I used unauthenticated access to the API as a quick and easy approach to solving the problem. Unfortunately, rate limits for unauthorized access causes the code to fail when testing the site using eleventy --serve since the data file processes every time you save any content file the project. With my GitHub account's 110 public repositories, it only takes 20 saves in an hour to hit the 60 API calls per hour limit.\nI decided to split this topic out into a separate post because I planned to build an Eleventy plugin for the authenticated version, letting an 11ty developer pass the API key and account name to the plugin when loading (instead of modifying the code), but I wasn't able to get to work properly since Eleventy plugins can't handle asynchronous code. If I ever get that working, I'll share the plugin with you.\nTo access the GitHub API in authenticated mode, all you have to do is generate an API key and pass it in the headers request to the REST API. The code is very similar to the earlier example (previous post), the only differences are that it uses an environment variable to store the GitHub API Key:\n\nAnd it passes the GitHub API Key as a header value in the call to fetch:\n\nTo access the repository list using Eleventy, create a file called repos.js and placed it in the site's _data folder (/src/_data/repos.js) and copy the following code into the new file (replacing the johnwargo in const githubAccount = 'johnwargo'; with your GitHub account name).\n\nI created a simple Eleventy site to demonstrate this at Eleventy Display GitHub Repositories (auth). This version displays the repositories as an unordered list on the sample page.\nGenerating a GitHub API Token\nBefore you can use this code, you must create a GitHub API token (GitHub calls them Access Tokens, so I'm going to switch to that name from here on) and save it as an environment variable on the system that builds your Eleventy site. I stored it in the environment on my local development system plus added it as an environment variable in my Netlify configuration (where I build and host the site).\nTo access your GitHub account's Access Tokens, open a browser, authenticate to your GitHub account, then navigate to https://github.com/settings/tokens to manage your account's access tokens.\n\nClick the Generate new token button, then select Generate new token (classic).\n\nPopulate the form that appears with a unique name for the access token. For scopes (access areas for the access token), the only option you need for this is public_repo.\n\nI could grant more scopes here, but that's unnecessary since all the code's doing is reading the public repo list.\nClick the Generate token button to create the token. GitHub generates the token and opens the manage tokens page where you have a single, immediate, and only option to copy the generated token. Copy the token right away and don't share it with anyone.  As soon as you refresh the page or navigate anywhere else in the browser, you lose your change to copy the access token.\nNext, create an environment variable on the system; the following figure shows part of the process on Microsoft Windows:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "December Updates to Eleventy Plugin Stats",
  "date":"Fri Dec 22 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703289600,
  "url":"/posts/2023/december-updates-to-eleventy-plugin-stats/",
  "content":"I made some enhancements this month to my Eleventy Post Statistics plugin.\nFirst of all, I added a avgPostsPerYear property to the collection to capture that metric; you can see the property in the sample page.\n.\nI also added the cli-logger to the plugin. This helps me more easily manage the output to the console.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Adding a GitHub Repository List to an Eleventy Site",
  "date":"Thu Dec 21 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1703203200,
  "url":"/posts/2023/github-repository-list-eleventy/",
  "content":"While working out at the gym the other day, I decided to add a list of all of my public GitHub repositories to this site; not because the site needs it, but because I wanted to learn how to do it.\nI quickly found a really easy way to do it, GitHub has a REST API I can access directly (without having to provide any authentication or API key) by invoking this URL: https://api.github.com/users/github-user-account/repos. Replacing, of course, the github-user-account`` with the user's account - which in my case is johnwargo`:\n\nThe API returns only 30 repositories with that API call, so, for larger repository lists, you must update the API call to tell it how many repositories you want returned using a per_page parameter:\n\nNote: The most you can return with a single API call is 100 repositories.\nWhen there's more than 100 public repositories in the account, you must retrieve each page manually:\n\nRepeating the process until the API returns an empty data set.\nThis is unauthorized access, so no login required; it only retrieves the public repositories which is exactly what I wanted for the site.\nNote: GitHub rate limits Unauthorized API access to 60 requests per hour. That limit doesn't exist for authenticated requests; you can read about that here: Adding a GitHub Repository List to an Eleventy Site (part 2).\nTo access the repository list using Eleventy, I created a file called repos.js and placed it in the site's _data folder (/src/_data/repos.js). Inside the file, I added the following code:\n\nThe code essentially calls the API repeatedly until it has all of the repositories then returns that to Eleventy so you can use the data in any of your site's pages. This creates a data source called repos that contains an array of repository entries; here's an example of how I use the data to render a Repositories page on this site.\n\nI created a simple Eleventy site to demonstrate this at Eleventy Display GitHub Repositories (no auth). This version displays the repositories as an unordered list on the sample page.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Migrating from Cipher to Cipheriv",
  "date":"Mon Dec 18 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1702944000,
  "url":"/posts/2023/migrating-from-cipher-to-cipheriv/",
  "content":"I have a Firebase project that uses a Firebase function to generate a URL containing encrypted data and another function to decrypt the data when someone invokes the URL (opens it in a browser). The functions use the Node.js Crypto library to do the encrypting and decrypting and I noticed recently in the library's docs that the library's createCipher method was deprecated and I needed to migrate my project to use createCipheriv instead. In this post, I demonstrate how I did it.\nBackground\nApparently createCipher has some issues:\n\nThis function is semantically insecure for all supported ciphers and fatally flawed for ciphers in counter mode (such as CTR, GCM, or CCM).\n\nMy particular application doesn't get a lot of hacker attention (that I know of anyway), but why keep an insecure algorithm lying around in your code, right?\nThe createCipheriv method configures an encryption algorithm that uses an Initialization Vector (iv) to increase randomness (or, actually, in my words, the perception of randomness) in the encrypted data generated by the cipher.\nI'm not an encryption expert and I'm sure there's a lot of folks out there that can go into great detail about this, but all you really need to know about createCipheriv is this:\n\nAn iv is a random string or buffer array of hex data of a particular size depending on the encryption algorithm being used to encrypt the data.\nYou should create a separate iv for every encryption event. I want to say must here, but that's not technically true, you could use the same iv every time (for all your data encryption), but then you're defeating the purpose of using a more secure cipher.\nThe app encrypting the data will use a cipher password and the iv to encrypt the data.\nThe app decrypting the data will use a cipher password and the iv to decrypt the data.\nDo not share the cipher password, that should remain internal to the code that encrypts and decrypts the data.\nYou don't have to hide the iv, you can pass it along with the encrypted data if you want. It's more secure if you protect the iv, but for my use case I don't have any choice but to include the iv with the data.\n\nThe Original Code\nNote: As you look at the following code examples, assume I have a secret password stored in a variable called cipherPassword and some data I want to encrypt in a JSON Object called theData.\nUsing the deprecated encryption method, my original code looked like this:\n\nIn this example, the code:\n\nCreates a Cipher that uses the aes192 encryption algorithm\nEncrypts the theData and finalizes it\nReturns a URL consisting of a URL root plus the encrypted data\n\nIn this example, the root URL looks like this: https://mycooldomain.com/?gcec= and the resulting URL looks something like this (using eclipses to indicate missing data):\nhttps://mycooldomain.com/?gcec=36e2eb4ea40299800e47dfaab20...11ef7db68ef07e74e9e411f43316735c46cffaaed\n\nUsing the deprecated encryption method, decrypting the data looked something like this:\n\nWhen it's done, the reqData is a JSON object that contains the original data properties.\nThe Migrated Code\nNote: As you look at the following code examples, assume I have a secret password stored in a variable called cipherPassword and some data I want to encrypt in a JSON Object called theData.\nConverting the code to use an iv when encrypting the data adds just a couple of extra steps to the encryption and decryption steps.\nTo encrypt, the code must create an iv consisting of a random string or buffer of hex data of a particular size depending on the encryption algorithm being applied to the data. My particular application uses aes192 which apparently requires an iv that's 16 bytes long. The Cipher library provides a simple method to do this: const iv = crypto.randomBytes(16).\nNote: To improve the security of your encrypted data, you should create a separate iv for every request.\nWith that in place, encrypting the data looks like this:\n\nNotice that the code appends the iv to the beginning of the encrypted data portion of the URL. I have to send the iv along with the encrypted data because the only delivery mechanism I have is the URL. Until now, hackers didn't know the encryption algorithm I used or the length of the iv, so anyone who saw the URL will not know what's iv and what's encrypted data.\nAgain, this isn't a heavily hacked app, so I'm secure including the iv in the package delivered to the user.\nDecrypting the data looks like this:\n\nThe first thing the code has to do is extract the iv from the URL. Since it's 16 bytes of hex, that means its 32 bytes of string, so the code pulls the first 32 bytes off of the content then converts it to a byte array using hexStringToByteArray I found at java2s.com.\nThe data to be decrypted is the rest of the data from the URL (starting at byte 32 through the end of the string).\nFrom there, the code calls the decipher method to decrypt the data and then parses the data into the JSON object reqData.\nConclusion\nI hope this helps you understand how to ",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Node.js",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Losing My Skills",
  "date":"Sat Dec 16 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1702771200,
  "url":"/posts/2023/losing-my-skills/",
  "content":"I feel like I'm losing some skills. I'm working on this Microcontroller-based project that I intended to have completed by Halloween (2023) but I wasn't able to get it working in time and, as I continue to work on it, I can't seem to finish it.\nThe project is a sleeping dragon in a mailbox project that I first wrote about in DFRobot mmWave RADAR. I have this sign that flashes lights inside the sign in a particular way until the mmWave device detects a human at which point it starts flashing the lights more...urgently.\nWhat's supposed to happen next is the sign's supposed to &quot;wake up&quot; the dragon creating sound, smoke and lights. I'm really excited about it, but I just can't get parts of it to work.\nEven though I wrote the post here about setting up and using the mmWave device, when I added it to the sign, it just hangs the sketch when I try to detect a human in front of the sign. I've tried two different mmWave boards on multiple microcontrollers and I just can't get it to work. This just makes no sense and I'm really frustrated about it.\nWhen it comes to waking up the dragon in the mailbox, I can't get the microcontroller in the mailbox to read pin state on the sign's microcontroller even though I published a post here about how to do that in Read Pin State Between Two Arduino Devices. This is ridiculous, I used to be able to make things like this work.\nDon't even get me started on the dragon in the mailbox, there's a lot of stuff going on there (lights, sound, smoke), but even though everything's coded and works, after a while the sketch simply panics the processor and it reboots.\nSigh, I don't know what to do. I have skills, more than 30 years of experience writing code and more than a decade working with microcontrollers and such. Apparently those skills no longer work for me.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Google Pixel Watch Failures",
  "date":"Sat Dec 16 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1702771200,
  "url":"/posts/2023/google-pixel-watch-foibles/",
  "content":"I'm a big fan of Google's Pixel phones and I ordered a Pixel Watch as soon as they were announced.I love the watch and wore it every day, but now I realize they're just an expensive experiment.\nMy first Pixel Watch broke after about 5 months; it stopped charging and took about a month for them to replace it. Fast forward 8 months later and it broke again, in the same way.\nI called Google and impatiently answered all of the ridiculous questions. For example:\nG: Which watch do you have?\nMe: The Google Pixel Watch\nG: But which one?\nMe: Dood, the box says Google Pixel Watch. You're asking and I'm giving you the exact, correct answer. There's the Google Pixel Watch and a Google Pixel Watch 2 and I have the Google Pixel Watch.\nUgh, so frustrating.\nSo I know the watch is more than a year old and they already replaced it once and I know that the warranty is likely one year. I called Google to understand what my options are for repairing the watch - paying Google to repair the product they sold me.\nAfter about 30 minutes on the phone with Google, they informed me that they would escalate my issue to the Warranty team.\n\nMe: Warranty team? But the watch is out of warranty.\nG: I have to escalate this to the warranty team\nMe: What's the device warranty?\nG: One year\nMe: It's beyond one year, so it's out of warranty and I knew that. What I'm asking for is what are my repair options?\nG: I have to escalate this to the warranty team\nME: but it's out of warranty?\nG: I have to escalate this to the warranty team\n\nSo I wait around to hear back from them and what do I learn except that there are no repair options for the watch.\n\nHello John,\nMany thanks for reaching out to the Google Pixel Buds Customer Care Team. We are glad to assist.\nAfter checking the case with our warranty department, we were able to confirm that the warranty expired on October 21st, 2023. Therefore, a replacement isn’t currently possible under your device's warranty.\nSince your device warranty period has expired, it’s not covered by the Google Store warranty policy. It’s recommended that you reach out to the retailer for available warranty options. And Google does not have any repair center.\n\nSeveral things are wrong with this response:\n\nThey responded as Pixel Buds Customer Care team, so apparently they don't even know it's a watch question.\nI already knew the device was out of warranty.\nI told them I knew the device was out of warranty.\nGoogle is the retailer, I bought it from them AND THEY KNOW THAT!\n\nNo repair options? Seriously?  Two devices couldn't last more than a year and they don't offer any options for repairing the device?\nThe device is just too damn expensive to replace every year. The trade-in for the broken watch is only $50US, which really doesn't help either.\nI guess it's time to go back to a $100 Fitbit. Sigh.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Axios Account Profile Edit Failure",
  "date":"Sun Dec 10 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1702252800,
  "url":"/posts/2023/axios-account-profile-edit-failure/",
  "content":"I can't think of any worse way to implement account profile editing than Axios does in their site today.\n\nSeriously? A separate edit link for every account profile property? That makes absolutely no sense. I'm setting up a new account, so I have to populate each of the fields on the form, so why force me to click edit for each and every one of them?\nIt just makes no sense.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Mounting the DFRobot mmWave RADAR",
  "date":"Thu Dec 07 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1701993600,
  "url":"/posts/2023/mounting-dfrobot-mmwave/",
  "content":"A while back, I started building a project using the DFRobot mmWave RADAR. However, as I described in IoT Component Manufacturers Ignoring Mounting Needs, I had some trouble figuring out how to mount the device in my project.\nAfter I published that article, I spoke with the product team at DFRobot and they informed me that they build that sensor expecting it to be mounted inside a commercial product. So it doesn't have an easy way to mount because my use case is different.\nMy project is the Sleeping Dragon in a Mailbox project that I was supposed to finish for Halloween this year, but ran out of time due to hardware incompatibilities (a long story that I'll write about later). I needed a way to mount the mmWave device on top of the sign and I finally decided on a simple implementation.\nAdafruit makes a quarter-sized Perma-Proto breadboard PCB that's just the right size for my purposes. I ordered some right-angle female headers and soldered them to the breadboard as shown in the following image.\n\nWith male headers soldered to the mmWave device, the RADAR points to the front as I needed it for my project.\n\n\nNext, soldered the connections from the ESP32 device I'm using for this project.\n\nFinally, I mounted the Perma-Proto board on top of the Sleeping Dragon sign.\n\nI could have done more to hide the wires and I definitely should have painted the Perma-Proto board black, but this solved my mounting issue and aims the mmWave device right where I want.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "zx for Simplified Node Process Spawning",
  "date":"Sat Nov 25 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1700956800,
  "url":"/posts/2023/zx-for-simplified-node-process-spawning/",
  "content":"At the All Things Open conference this week, I presented a session entitled Write Shell Scripts Using JavaScript and zx. The session introduced Google’s zx (https://github.com/google/zx) project and another project called execa (https://github.com/sindresorhus/execa) and highlighted examples of each. The tools are pretty cool and help developers in some very specific use cases. This post covers the zx specific content from the session; I’ll publish the execa content from the presentation in a separate post.\nZx provides JavaScript developers with a simplified interface around Node’s child_process module, delivering a quick, easy and simple way to spawn external processes from a Node application.\nNote: When I wrote the title and abstract for the session, my view was that zx helped developers deliver a single script to automate processes on multiple platforms (Linux, macOS, and Windows). But that’s really not true since zx only helps with spawning external apps, for general purpose file system manipulation (copying, deleting, moving files and so on) Node already has the fs (https://nodejs.org/api/fs.html) and fs_extra (https://npmjs.com/package/fs-extra) modules.\nBackground\nSoftware developers frequently need to automate stuff. There’s a lot of tools available to manage things like installing dependencies, executing build and deployment processes, executing integration tests and so on, things like DevOps pipelines, node package manager (npm), GitHub actions and so on. There’s so many tools and options that I’m not going to even try to list even a small portion of them.\nFor a single developer like me working in local developments in Windows and macOS, or when deploying software or tooling to setup a demo environment for repeated demonstrations (that need to be executed by others), I often resort to writing shell scripts (linux or macOS) or batch/command files (Windows) to simplify the process. These are short little scripts that do one or more simple things that dramatically simplify the work required to perform the individual steps repeatedly.\nBut since I write software on both macOS and Windows, to do this I have to write both shell scripts and command files every time. The command palette available to me on each side is different, so when I do this I’m writing in two completely different languages with some overlap between the two.\nWhy I’m Interested in zx\nAs I started looking at zx, I was looking for:\n\nA way to execute shell commands on multiple platforms without having to code a bunch of if/then statements to deal with different platform’s inconsistencies\nSupport for:\n\nAt a minimum Microsoft Windows\nSupport macOS and/or Linux too\n\n\nStand-alone scripts, no overhead files polluting the current project folder.\nNo new language learning.\nSupport for asynchronous tasks.\n\nSince I’m already a JavaScript/TypeScript developer, I’d prefer to be able to do all this in either one of those languages (preferring TypeScript).\nI Could Use Node For This, Right?\nAs an experienced JavaScript/TypeScript and Node.js developer, I know I can write scripts in JavaScript or TypeScript and Node to do a lot of this automation. Node’s fs and fs_extra modules deliver a lot of capabilities developers can use to interact with the file system to copy, move, delete, and manipulate files.\nDoing these types of things in Node however, especially in a non-Node project folder, leaves some extra files around (like the package.json file and node_modules folder) when installing packages used by your scripts. What I’m looking for is a cleaner way to do this.\nNode even offers a child_process module that exposes capabilities that allows developers to spawn external applications or processes from a Node application/module. Unfortunately, using Child Process is sometimes difficult since you must carefully manage executing steps in sequence plus you must also directly manage process output sent to stdout or stdio.\nI simply don’t want the hassle. Since zx abstracts away the complexity of child_process, the resulting code just looks simpler and easier to maintain.\nWhy not use PowerShell?\nYou’re right, I could use PowerShell for this. There are, however, some problems with this approach (for me anyway):\n\nIt requires that I have PowerShell installed on every system where I want to use it. As I’m installing zx everywhere for this, installing PowerShell instead is no big deal.\nI don’t know how to code scripts in PowerShell.\n\nThe second bullet for me is the most important, I don’t want to have to learn any new languages to accomplish my goals.\nIntroducing zx\nzx is a Google project that delivers a Node module that dramatically simplifies spawning processes in Node applications. It also delivers a runtime environment for node scripts so, unless I need to use external Node modules (zx loads a couple of common ones by default), I can run my scripts without leaving a bunch of detritus lying around in the project folder.\nHere’s how Google describes zx (from the repo",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Developer Tools",
  
    "JavaScript",
  
    "Node.js"
  
  ]
  },

  {
  "title": "Visual Studio Code Progress Cancelled by Async Task",
  "date":"Sat Nov 25 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1700956800,
  "url":"/posts/2023/vscode-extension-progress/",
  "content":"I'm working on my first Visual Studio Code extension and as part of the extension's work, it calls a long-running external API that could take 30 seconds or more to complete. I started looking for way to display a progress dialog and discovered the vscode.window.withProgress. As I looked through the different examples I found out there, they all showed how the code that displays and manages the progress item decides when to close the window.\nFor my project, I had a separate process deciding when to close the progress window and it took me some time to sort out how to make everything work. You can find the complete Visual Studio Code extension code in Visual Studio Extension Progress Demo.\nAsynchronous Task\nI didn't want to pull over the complete code from my other extension project, so I created a dummy asynchronous task that basically sits for a specific number of seconds (in this case 10), then cancels the progress window; I'll explain the customCancellationToken object later.\n\nChange the value in the delayValue constant to modify how long the progress window appears before closing.\nProgress Window\nTo create a progress window, use the following code as a framework:\n\nNotice that the progress window is cancellable; to trigger cancellation, you need a CancellationTokenSource:\n\nIt's the cancel() method on the customCancellationToken object that the asynchronous task calls when it's done waiting.\nNext, you create an event handler for the cancellation event:\n\nThe code essentially destroys the cancellation token and resolves the promise keeping everything running up to this point.\nNext, you need something to update the progress window periodically so the user can tell that something's happening. The following code uses a JavaScript interval to upgrade the progress window every second. In this example, the code adds a period to the end of the status message, resetting after 5 periods.\n\nPutting this all together, here's the complete progress window code:\n\nThe code:\n\nCreates the cancellation handler\nStarts the taskRunner task\nKicks off setInterval to loop infinitely until the task runner tells it to cancel.\n\nUnlike the other examples I found online, this example cancels the progress window from an external task.\nFull Code\nHere's the complete code for the extension.\n\nTo run this code in Visual Studio Code:\n\nClone the Visual Studio Extension Progress Demo repository.\nOpen the cloned project in Visual Studio Code\nIn a vscode terminal window, execute npm install\nPress the F5 key to start debugging the extension.\nIn the new Visual Studio Code window that opens, open the Command Palette and type select the Progress Demo option.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Developer Tools",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Pumpkin Controller Native Apps for Windows",
  "date":"Sat Nov 18 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1700352000,
  "url":"/posts/2023/pumpkin-controller-native-apps-for-windows/",
  "content":"In the post I published earlier today I mentioned that someday I might make a native windows version of my Pumpkin Controller app (See Glowing Pumpkin). Well apparently today's the day.\nFlutter App\nI guess I wasn't paying attention when I wrote that because Flutter apps are cross platform apps and all it took me was a minute or so to create, build, and test the Windows version of the app. Here's a screen shot:\n\nEverything seems to work OK except that the Toast module I used doesn't support Windows, so you won't see any notifications when it completes successfully or when it fails. I'll see what I can do to fix that.\nI'll have to figure out how to generate a Windows executable out of Android Studio and publish it in the repository. Stay tuned on that one.\nFireMonkey App\nI did a little Delphi development this weekend, so when I decided to build a native Windows version of the Pumpkin Controller app I used RAD Studio and FireMonkey to create a cross-platform native version of the app using Object Pascal. Here's a screen shot of the app:\n\nI didn't do anything to make the app pretty, I was just trying to figure out how to make it work using FireMonkey.\nI generated Win32 and Win64 executables and published them as Releases in the Pumpkin Controller FireMonkey project.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Flutter",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Accessing an Arduino ESP32 Web Server",
  "date":"Sat Nov 18 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1700352000,
  "url":"/posts/2023/accessing-an-arduino-esp32-web-server/",
  "content":"This post is the continuation of Arduino ESP32 Web Server on a Processor Core where I described how to code a web server and run it on a dedicated core in an Arduino ESP32 project. That article was very long, so I didn't describe much about how to connect to that web server from a desktop PC or mobile device, so I cover that here. Here's a video of the web server project working with the mobile app: https://youtube.com/shorts/BMP7LUCIwN0.\nIf you watch the video, you'll notice that I mentioned making it flash purple three times but in the video it only seems to flash twice. That's because I already had purple selected, so the first purple flash didn't actually do anything.\nNote: I do not have any plans to show how to connect to this web server from another microcontroller-based project; let me know if this is something you would like see. There are a lot of examples of Arduino projects connecting to a web server over Wi-Fi, the only difference here would be the local URL for the web server.\nBackground\nThe premise for this project is to use a desktop PC or mobile device to remotely control the LED matrix inside the pumpkin.\nYou can build a native desktop (which includes laptops) application and access the microcontroller-driven web server (MDWS) very easily but who wants to do all of that heavy lifting? Besides, do I really want to haul a laptop around to control the pumpkin? For testing, however, there are existing tools that make controlling the MDWS a simple process. More on this later.\nSince I want to control the pumpkin from a variety of devices, I assumed that using a web browser would be the fastest, easiest, and most consistent approach to use.\nIt turns out that's simply not the case.\nYou can build a web application and use it to access the MDWS pretty easily. On your desktop PC, fire up your web app editor of choice, code the app, load the application in your browser, then access the MDWS. Here's a link to the app I built for this project: Pumpkin LED Controller; I discuss this app later in this article.\nAs long as the PC running the browser/web application and the ESP32 web server are on the same local Wi-Fi network, it works. If you host the web application on a pub web server somewhere (like Netlify) you can make it work, but not out of the box; there are special settings you must change in the browser to make it work (described below).\nMy little microcontroller-driven ESP32 web server doesn't have an SSL/TLS certificate installed. Yes, I know I can generate and install it on the device, but I chose not to take that painful approach, because browsers won't like self-signed certificates. When I host the web app on a custom domain (in this case https://pumpkin-controller.netlify.app/), the browser doesn't like cross domain access (the web app hosted at pumpkin-controller.netlify.app connecting to a web server on a local network). The browser blocks it and that's where the special settings come into play (telling the browser to ignore the security risk).\nRunning the web app on a mobile device changes everything.\nMobile browsers flatly refuse to let a web app hosted in one domain access my microprocessor-driven web server. That browser setting that instructs the browser to ignore the security risk simply does not exist on mobile devices; from my testing and what I learned through research, there's nothing I can do - it's never going to work.\nSo, what are your options for controlling the Pumpkin from a mobile device? The only option I could find is to do it using a native mobile application. There are a variety of options for building the mobile app:\n\nNative Android app written in Java or Kotlin.\nNative iOS and/or iPadOS app written in Objective-C or Swift.\nNative application written in Dart using Flutter.\nNative Hybrid application (such as Apache Cordova, Ionic Capacitor, or even Electron).\n\nI'm really not a native mobile developer even though I published multiple books on the topic, so that option doesn't work for me. I wrote 4 books on Apache Cordova, so I know I could do that pretty easily, but that particular technology is dead. I've also written a bunch of Ionic apps (I even have one in the app store: Time Slicer) so I could use that option if I wanted. My favorite mobile app development approach is Flutter, so for this project I built a Flutter app called Pumpkin Controller that you can install and use to control the pumpkin.\nYou'll find detailed information for each of these topics in the following sections.\nPostman\nAs I mentioned in the Background section, you can use a native desktop/laptop app to access the microprocessor-driven web server. I'm not suggesting that you write your own, but you could certainly do that; I may even spend some time doing that and share the project here.\nThere are many API testing applications available to developers and they're an excellent way to exercise the microprocessor-driven web server. My favorite is Postman. Postman is interesting in that they offer a fre",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "ESP32"
  
  ]
  },

  {
  "title": "Outlook Windows Delete Empty Inbox Folders",
  "date":"Fri Nov 17 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1700265600,
  "url":"/posts/2023/outlook-windows-delete-empty-inbox-folders/",
  "content":"My primary working system runs Microsoft Windows and I use Microsoft Outlook as my email and calendar manager for my personal email account. I've moved my Outlook PST file from system to system over the last, oh I don't know, how many years (at least 20 years or so) and the file's HUGE (about 1.5GB right now). To keep the file size manageable (if you call 1.5GB manageable), I use Outlook's Automatic Archive feature to move older Inbox items to an archive file (which right now is about 5GB).\n\nI recently noticed that had a bunch of empty folders left around in my inbox because the archive process emptied them. I wanted to clean them all up, no need to keep empty folders around, but didn't want to delete them manually - mainly because my Inbox has hundreds of folders and right before I wrote this post it had 102 empty ones.\nSince I love automating tasks with software, and it's been a while since I've written anything in Delphi (Object Pascal), I decided to create a little utility I can run periodically to delete my Inbox's empty folders. I just completed the app and published it, it's called Outlook Delete Empty Inbox Folders and here's the latest executable.\nTo use the app, you simply launch it and it accesses the default Outlook profile's Inbox. When you click the Analyze button, it scans the Inbox looking for empty folders. When it finds an empty folder, it adds it to the empty folder list on the app's main screen.\n\nWhen you're all set and you confirmed that the list looks correct, click the Delete button and the app deletes all of the empty folders in the Inbox.\nEnjoy!\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Windows",
  
    "Microsoft Outlook"
  
  ]
  },

  {
  "title": "Eleventy Splitting Category Data Across Two Table Columns",
  "date":"Fri Nov 17 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1700265600,
  "url":"/posts/2023/eleventy-two-table-columns/",
  "content":"The Categories list on this site is getting pretty long, so one of the things I wanted to do this weekend was migrate the Unordered List (&lt;ul&gt;&lt;/ul&gt;) the site used today into a two column table. I asked Bard and it generated relatively useless code for me; after three tries I finally got something that looked like it would work, but didn't.\nAs I poked around in the Liquid docs, I noticed that Liquid has a tablerow tag I could use for this. Basically you give it a collection and number of columns and it automatically generates columns for you.\n\nWith that in mind, I replaced the site's Category page content with the following code:\n\nIt generates the columns exactly as expected and saved me a lot of work hand crafting Liquid code to do it.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Using UDP Broadcast to Synchronize Actions Across Arduino Devices",
  "date":"Sat Nov 04 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1699142400,
  "url":"/posts/2023/arduino-udp-sender/",
  "content":"With my Glowing Pumpkin Project Refresh my ultimate goal was to synchronize LED Matrix colors across multiple devices so I could place one in a pumpkin in each of the front dormers in my house. I finally got it all working and published the project yesterday at Glowing Pumpkin Sync UDP.\nHere's the project in action (without pumpkins this time):\nhttps://youtube.com/watch?v=L2v5T3hO6S4\nWith this version of the GLowing Pumpkin project, you deploy one Glowing Pumpkin Xiao 5x5 BFF device with the Sender sketch deployed to it and all of the other devices with the Receiver sketch. As long as all of the devices are one the same Wi-Fi network, they all connect to the network and the Sender starts sending commands to each of the Receiver devices using UDP Broadcast messages.\n\nArduino Sender\nHere's the loop code from the Sender:\n\nIt's essentially the same code from the original BFF project but as soon as it decides to flicker (like lightning inside the pumpkin) or what color to display, it sends a command to the Receiver devices to do the same thing.\nArduino Receiver\nIn the receiver, the sketch sets up an UDP listener that parses the incoming packet, then calls the local function to flicker the LED Matrix (when it receives the f command) or fade to a particular color (when it receives the c:# command where the # refers to a particular color in the color array).\n\nRaspberry Pi Pico W Sender\nAs I worked on this project, I had some trouble getting the Sender sketch working as an Arduino project. I finally figured it out, but as I tried different solutions to get this working I built a Python version of the Sender for the Raspberry Pi Pico W. If you want to use this version, run the Sender on the Pico and run the Receiver on all of the Glowing Pumpkin Xiao 5x5 BFF devices.\nWrap-up\nThis all works really well except that I periodically have some difficulty connecting several of my devices to my Wi-Fi network. I'm not sure whether it's a problem with the Seeed Studio Xiao devices or my network (Nest Wi-Fi) not trusting the devices because I keep rebooting them during development. I found that with one of the devices, if I let it sit for a couple of hours, it connects just find. For another device, I have to fiddle with it for a while to get it to connect. I'm going to swap out the hardware (I have some spares here) and see what happens.\nI hope you enjoy this project, I'm excited that I was able to accomplish what I wanted to do using UDP broadcasts.\nHere's links to the articles in the Glowing Pumpkin Xiao 5x5 BFF series:\n\nGlowing Pumpkin Project Refresh\nArduino UDP Broadcast Receiver\nArduino ESP32 Web Server on a Processor Core\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Arduino UDP Broadcast Receiver",
  "date":"Wed Nov 01 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1698883200,
  "url":"/posts/2023/arduino-udp-broadcast-receiver/",
  "content":"Back in August, I refreshed my Arduino Glowing Pumpkin project and published an article about it in Glowing Pumpkin Project Refresh. A short while later, I figured out how to put a web server in it and control the LED matrix using a web application (desktop browser only) or a mobile app (smartphone or tablet) and wrote about it in Arduino ESP32 Web Server on a Processor Core. That was a lot of fun and I was glad I got those projects out there before Halloween.\nFor many years, we put glowing pumpkins running the Glowing Pumpkin code in each of the dormers on the front of the house. One of the things I always wanted to do was synchronize the LED colors across all of the pumpkins. As soon as I completed the dual-core web server version (the second link at the top of the article) I started actively working on building a version that did that.\nI knew the web server approach wouldn't help me because its server focused and I didn't want to have to build something that sent requests to multiple servers to synchronize them. Another possible option is to use Web Sockets and have each pumpkin sync with a server process, but that seemed like more work than I was willing to do.\nThe mobile app I created to control the web server version of the project is able to easily use a TCP connection to an Arduino device. With that in mind, I started investigating whether I could use TCP's close cousin UDP to deliver synchronization across the pumpkins. It turns out it can and I quickly updated my mobile app (Pumpkin Controller (Flutter)) to support both HTTP requests over TCP (for the web server version) and UDP broadcasts (for the synchronized version). Basically it works something like this:\n\nEvery time you tap one of the buttons in the app, it sends a UDP broadcast messages on the local network and any device listening for the messages will read the message and act upon them.\nIn the mobile app, open settings and from there you enable the UDP broadcast capabilities in the app as shown in the following figure.\n\nNext, you install the Glowing Pumpkin Receiver (UDP) code on all of the Glowing Pumpkin BFF devices you want controlled by the mobile app and you're all set.\nHere's a demonstration video showing synchronized pumpkin LEDs in action.\nhttps://youtu.be/beevHJM8poQ\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)",
  
    "Flutter"
  
  ]
  },

  {
  "title": "Read Pin State Between Two Arduino Devices",
  "date":"Tue Oct 31 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1698796800,
  "url":"/posts/2023/read-pin-state-two-arduino/",
  "content":"As I worked on my latest Halloween project, I realized that one of the things I wanted to do was read the pin state from a different/separate Arduino device. My project used two Arduino-compatible devices for different purposes and I wanted to be able to send a signal from one to the other.\nI looked around for a while and found a bunch of Forum questions on this topic and answers for the most part, but I couldn't find a post that actually described it in detail. This post does that.\nTLDR\n\nYes, it works and is easily done.\nConnect the ground (GND) connectors on the devices together. GND to GND, use a black wire if you can, its generally a standard for GND connections.\nConnect a Digital Pin on one Arduino device to a Digital Pin on the other Arduino device. No, they don't need to be the same pin number on each device, but make sure you track the pin number accurately in your sender and receiver code. Use whatever color you want to use for the connecting wire.\nWrite some code in the sending device's setup() function that configures the connected digital pin for OUTPUT mode. The code looks something like this: pinMode(PIN, OUTPUT); - replace PIN with the pin number on the sending device.\nWrite some code in the receiving device's setup() function that configures the connected digital pin for INPUT mode. The code looks something like this: pinMode(PIN, INPUT); - replace PIN with the pin number on the receiving device.\n\nWhen the sending device wants to trigger something on the receiving device, set the pin on the sending device to HIGH using digitalWrite(PIN, HIGH);. When the triggering event ends, set the pin on the sending device to LOW using digitalWrite(PIN, LOW);\nOn the receiving device, execute some code that periodically checks the status of the receiving pin's status using code that looks something like this uint8_t state = digitalRead(PIN);. When the sending device is sending a signal, the value in state will be HIGH otherwise it will be LOW. When it's HIGH, execute the code you want run whenever the pin state is HIGH otherwise execute the code you want run when it's LOW.\nThat's pretty much it. There's a much longer description in the rest of the article.\nMore Details\nTo read pin state on an Arduino device (in an Arduino sketch), you generally make a circuit between ground (GND), a voltage source, and a Digital or Analog pin on the Arduino. You configure the digital or analog pin for INPUT mode then read the value periodically to determine whether the circuit is HIGH or LOW. In your sketch, you do something based on those two states. There's a bunch of articles in the wild on this, so I'm not going to go into any more detail how to do that. There's an excellent example in How to Wire and Program a Button and you can find an article I wrote on the topic in Hackspace Magazine - Issue 2.\nFor this example, I'm not trying to read a button, instead I want to be able to change the voltage state on an Arduino device and read that state on a different Arduino device. This is actually easier than the previous description (previous paragraph) but I don't know why since I'm not an Electrical Engineer. Note: I'm just a software guy who plays with hardware.\nFor this to work, both devices must share a common Ground connection. The easiest way to do this is to connect the GND pin on one Arduino to the same labeled pin on the other Arduino. Next, you must connect an input/output pin on one Arduino to an input/output pin on the other Arduino. The following figure illustrates these connections.\n\nIn the image, both devices are Seeed Studio Xiao Arduino-compatible devices and they have very similar pin configurations. I selected these devices because I could easily put two of them on a small breadboard. You can do this with Any Arduino devices, just pay close attention to the pin configurations.\nHere I connected the GND pin on both devices using a black wire (black traditionally indicates a ground connection) and I connected the A0/D0 pin on each device to each other.\nNote: In the code below I just noticed that I used the A0 pin designator out of habit, but that works fine since the pin is both an analog and digital input/output pin. I could very easily have used D0 to define the pin.\nI used the same pin on both devices because I could (and possibly because I have a little OCD), but there's no reason for it other than I wanted to. All that matters is that you select a pin that works as a input and/or output (I/O) and they don't have to be the same pin on each device; use what's available.\nWith the devices connected, now it's time to write some code.\nSender\nFor the code sending the signal to another device you must first configure the device for output mode using:\n\nYou only want to do this once, so do it in the Arduino sketch's setup() function.\nNext, you must define the code that triggers sending the signal to the other device. I don't have a good scenario to share here, so what I did was put a timer in the loop() function an",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Eleventy Date-only Filter",
  "date":"Mon Oct 30 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1698710400,
  "url":"/posts/2023/eleventy-date-only-filter/",
  "content":"I was looking at the site's stats page yesterday and noticed that the output for First Post and Last Post date included an empty time 00:00:00 GMT+0000 (Coordinated Universal Time).  This is unnecessary since there was no time component in those values, only a date. Here's what it looked like:\n\nSo I set out to fix the output so it looked exactly the way I wanted, which is:\n\nNo time displayed\nThe date formatted as text strings rather than numbers only\n\nThe site captures the first and last post dates through my Eleventy Site Statistics plugin and I started there thinking I would simply force the date format I wanted there. I checked the plugin's source code and saw that the plugin captures those dates as JavaScript Date objects. That was the right thing to do, and I was glad I did the right thing when I created that plugin. Saving it as a Date object allows the user (in this case me, but it could very well be you) to do whatever they want with the date format.\nIf I switched the plugin to store the date as a formatted string, formatted the way I wanted it, then I'd implement a breaking change in the plugin and force a particular date format on all other users of the plugin. I don't want to do either of those things.\nNext, I popped open the site's eleventy.config.js file and decided to add a new filter for this behavior called dateOnly:\n\nThe filter accepts a JavaScript date value and an optional locale; if the user doesn't specify a locale, the filter uses the default &quot;en-us&quot;.\nInside the filter, the code converts the incoming date value into a JavaScript Date object. This allows the code to apply all sorts of Date-supported formatting options. In this case, the code specified the exact formatting options to use in the options constant.\nWith my formatting options defined, the code then returns the date value as a formatted string using the toLocaleDateString() method passing in the locale (which adds locale awareness and language to the output (for month names, for example)) plus the options constant (which applies my formatting options to the output). The resulting output is the date formatted just the way I want it.\nTo use the filter in your site, simply add the filter to the templated content like this:\n\nAnd now the resulting page looks exactly like I want it:\n\nTo use a specific locale, like Portuguese for example, simply add the locale to the filter like this:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "A Better Arduino MicroFogger Controller Redux",
  "date":"Sun Oct 29 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1698624000,
  "url":"/posts/2023/arduino-microfogger-control-more-better/",
  "content":"In my previous post, I demonstrated a better way to randomly generate smoke using the Vosentech MicroFogger 5 Pro from an Arduino sketch. That version was better because it didn’t block the main loop, instead it let other stuff while it generated smoke and waited.\nThat example was good, but in order to teach the topic, I wrote more code than I needed to to solve the problem. I was demonstrating a method for periodically checking a timer rather than blocking other activities using delay().\nI figured someone would look at that code and say “yeah, but there’s a better way to do that” and yes, there is. There are a lot of better ways to do what I did; this post demonstrates one of them.\nInstead of using two separate functions to start smoke and start a wait period,  you can do it all in one function. With that in place, you only need two functions to manage both the smoke and delay between smoke events instead of three.\nI'll show the complete code at the end of this article, but you can also access it on GitHub at microfogger-random-smoke-better.\nFor this example, the initialization and setup() code remain essentially the same, you can refer to the previous post for details. All I did was rename startSmoke() to setSmokeState(); you’ll see why in a minute.\n\nIn loop() I merely changed the name of checkSmokeTimer() to checkSmokeState().\n\nI made those changes because in this example, we’re no longer turning smoke on or starting a wait period, we’re managing the state of smoke generation. When the smoke state is on (true), the sketch turns on the smoke generator, when smoke state is off (false) the sketch turns off the smoke generator. For both states, the sketch maintains a single timer and uses it to manage both generating smoke and the wait periods in between.\nLets look at the checkSmokeState() function:\n\nThe only change here is that I removed the if/then statement based on isSmoking and replaced it with a single line of code that calls setSmokeState() and passes in the opposite of the current state (isSmoking true or false).\nAll the magic is in the setSmokeState() function:\n\nThis new function covers the tasks required from the earlier example to turn smoke on (startSmoke()) or start a delay (startDelay()) in a smaller package.\nFirst, the function uses the boolean value passed to the function (the state we want to put the sketch in) to determine whether we want the smoke pin or LED pin on (HIGH) or off (LOW). The sketch does this by assigning high or low values to the state variable based on whether smokeState is true or false.  With that in hand, the sketch uses that value to turn the smoke pin and LED Pin on or off.\nNext, the sketch simply resets the timer with a new start time and duration then the whole process kicks off again.\nThis sketch uses less code to do the same thing as the previous example and instead of setting pin state in two different functions (with hard coded logic) it moves that into a single function and therefore simplifies the code.\nThe code may be a little harder to read, but smaller code means more memory space in the Arduino memory for code to do other things.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino"
  
  ]
  },

  {
  "title": "A Better Arduino MicroFogger Controller",
  "date":"Sat Oct 28 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1698537600,
  "url":"/posts/2023/arduino-microfogger-control-better/",
  "content":"In my previous post, I demonstrated how to control a Vosentech MicroFogger 5 Pro from an Arduino sketch. The example I provided there was simple and just showed how to control the smoke generator, turning on and off smoke generation for random periods of time.\nNote: I published an even better (more better) version of this post's code in A Better Arduino MicroFogger Controller Redux.\nThat example has an issue, a big one, the sketch can't do anything while the sketch waits to turn off or turn on the smoke. I suggested at the end of the article that you could write the sketch in such a way as to let the sketch do other things. This post describes that alternate version. I'll show the complete code at the end of this article, but you can also access it on GitHub at microfogger-random-smoke-better.\nThis version of the sketch starts mostly the same as the other version, with a few additions.\n\nI added some variables that weren't in the other version:\n\nThe boolean isSmoking allows the sketch to understand whether it's generating smoke or waiting before generating smoke again.\nThe integer timerDuration keeps track of how long the sketch generates smoke or waits between smoke generation. It tracks the time in milliseconds (1,000 milliseconds equals one second). Basically, the sketch resets this value with a randomly generated number of milliseconds every time it interacts with the smoke generator. In the previous example, the number of milliseconds was passed to the delay() function, so the sketch 'used' it only when starting a wait. In this example, we need to be able to track the wait duration external to any call to delay() mostly because this version of the sketch doesn't use delay().\nThe long integer startTime tracks the current time, in milliseconds, as tracked by the Arduino. Basically, the Arduino platform has a timer chip and starts counting milliseconds from the moment the Arduino powered on (resetting at about 50 days). This provides a sketch a very rough way to track time and calculate time between events or activities. The sketch uses this to help calculate how long since an event (starting smoke generation or waiting between generation events) started so it can determine, using timerDuration whether it's time to end the event.\n\nDuring setup(), the sketch also calls startSmoke() to begin smoke generation; I'll explain how that works a little later.\nThe loop() function in this example changed dramatically. Previously, the loop did all of our smoke generation and waiting to generate smoke again. In this version, the loop simply makes a check to see if its time to end an event and start the next one (checkSmokeTimer). This gives the sketch time to do other activities, as you can see from the comments in the code:\n\nAs long as the code the sketch executes before and/or after the timer check doesn't take too long, the sketch will accurately track the time assigned for each smoke event (generating and waiting). If your sketch's other code executes long-running actions or uses delay() with more than 500 milliseconds or so, then this breaks down. For other long-running events, your sketch must use a similar timer approach (described below) to ensure every part of the sketch gets time to execute and share processor cycles with the rest of the sketch.\nAlright, lets get into the meat of the sketch.\nThe startSmoke() function turns on the smoke generator and onboard LED just like the previous example (uses the same code), it also sets those three new variables I described at the beginning of the post. It sets the isSmoking boolean to true (you know, because we're generating smoke at this time). In the startDelay function I set it to false and that's how the sketch knows which 'state' its in.\nNext, it assigns the current time to startTime (remember, in milliseconds) and assigns a random number of milliseconds between the values in MIN_TIME and MAX_TIME to timerDuration. Simple subtraction between the two values performed later tells the sketch whether it's time to stop generating smoke, I'll explain this later.\n\nThe startDelay() function works exactly the same except for two differences:\n\nIt turns smoke generation and the onboard LED off.\nIt sets isSMoking to false because we're no longer generating smoke\n\nThose two actions puts the sketch in delay mode, waiting for the next opportunity to generate smoke.\n\nFinally, and this is where all the magic happens, the checkSmokeTimer() manages smoke generation state and kicks off smoke generation or waiting based on that state.\nThe first thing the sketch does is check to see if the timerDuration contains a value greater than zero. If for any reason you want to stop this process all together, some other part of the sketch can change the value assigned to timerDuration to zero or any negative integer and this check for zero causes checkSmokeTimer() to skip execution all together. To restart the process, make a call to startSmoke();\n\nNext, the function subtracts the start time fro",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Controlling the Vosentech MicroFogger From An Arduino",
  "date":"Fri Oct 27 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1698451200,
  "url":"/posts/2023/arduino-microfogger-control/",
  "content":"Note: This post is just a starting point, I published a better version of this post's code in A Better Arduino MicroFogger Controller and an even better (more better) version in A Better Arduino MicroFogger Controller Redux.\nFor this year's Halloween project, I needed a battery powered smoke machine. I purchased a couple of different devices to try them out, and finally settled on the Vosentech MicroFogger 5 Pro.\nOne of the reasons I selected the MicroFogger device is because they offer an add-on board that allows you to control the smoke machine from an Arduino (or similar) device: MicroFogger control cable and breakout board. With this board, you can charge the MicroFogger battery and control smoke generation at the same time.\nIn this post, I'll show you how to control the MicroFogger from an Arduino sketch and randomly generate smoke; here's a video demonstrating the end result:\nhttps://youtu.be/hNl9zjcL8mQ\nTo use the controller board to control the MicroFogger from an Arduino sketch, you'll have to change two settings on the device. Follow the instructions in the user guide to navigate to the Advanced settings section. There, you'll first need to disable Charge Lock (set it to OFF) so you can charge the device from the connected Arduino while using it.\n\nNext, enable the control cable (set it to ON) as shown in the following figure.\n\nWith the correct settings in place, connect the Arduino-compatible device to the controller card as shown in the following figure. For this, I connected the 3V, Ground, and the A0 connections on the controller card, in this case an Adafruit Feather, to the MicroFogger.  Plug the controller cable into the controller card and MicroFogger and you're all set.\n\nTo control smoke generation, all you have to do is set the Arduino output pin (A0 in this example) to HIGH and as long as it's HIGH, the MicroFogger will generate smoke. Turn the output pin off (LOW) to stop smoke generation.\nIn the sketch below, I defined three defines at the beginning of the sketch. These are essentially compiler directives that instruct the compiler to replace the variable name with the value everywhere in the sketch. It allows you to change the pin connected to the MicroFogger in a single place rather than multiple places throughout the code. The MIN_SMOKE_TIME and MAX_SMOKE_TIME defines specify the minimum and maximum number of milliseconds used to randomly generate smoke and wait before generating again.\n\nThe setup function configures the Pin connected to the MicroFogger control board for OUTPUT meaning the sketch can set the output of the pin to HIGH or LOW turning the MicroFogger on and off. It also configures the onboard LED on the Feather device. The sketch uses this to turn the LED on at the same time as it turns on the MicroFogger; this helps you troubleshoot the sketch if it doesn't seem to be working correctly since the LED should be on any time the MicroFogger is on.\n\nFinally, the loop function turns on the smoke and LED, waits a random number of seconds before turning it off. Next, it waits another random number of seconds before repeating the process.\n\nThat's it, there's not much to it; here's the complete sketch:\n\nYou can find a Gist for it here: https://gist.github.com/johnwargo/e6b19e2d2b905ac7a61d061ea952e482.\nIn real world scenarios, you won't want to tie up the loop function with delays since nothing else happens while the device waits for the delay to complete. When I get a chance, I'll post something here that demonstrates how I implement that functionality.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino"
  
  ]
  },

  {
  "title": "Windows 11 Annoying Save As Dialog Categories",
  "date":"Sun Oct 22 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1698019200,
  "url":"/posts/2023/windows-11-annoying-save-as-dialog-categories/",
  "content":"In the Windows 11 browser download dialog, Microsoft categorizes the target folder contents based on which folders you accessed most recently. Windows shows folders categorized by Today, Yesterday, Last Week, Earlier This Month, Last Month, then Earlier this year as shown in the following figure:\n\nThey did this, I think, in the mistaken belief that this is helpful for the user but I think they really missed the mark. I can see the value in doing this when downloading multiple files, but the browser automatically returns to the same folder for subsequent saves, so it still doesn't make sense.\nI hate this 'feature', I absolutely hate it and I gnash my teeth every time I encounter that f#cked up dialog.\nIn my use case, I save all downloads to my system's Downloads folder and that folder contains a hundred folders or more. When I'm saving a file, I'm looking for a specific folder to put it in and I automatically scroll and scan looking for the folder name. The list of folders should be listed alphabetically, so scrolling and scanning for a specific folder is no big deal. With this abomination, Microsoft leaves me no choice but to actively look at each folder name in each category to find the target folder.\nMore gnashing of teeth.\nPeriodically, when I get really frustrated by this 'feature', I hop online and start looking around for a way to put that list back to an alphabetical listing.\nSearch Engines gleefully show me instructions for how to remove categorization in a single folder in Windows Explorer, but generally have nothing to say about this Save Download folder. Sigh.\nThe other day though I hit the jackpot!!! I found a support ticket where a Microsoft Support engineer recommended a third-party tool called WinSetView that allowed me to fix this horrible problem.\nI downloaded the utility, extracted the files to a folder, then executed the main application. The app has a lot of options, but I didn't pay attention to any of them, I simply accepted the default options and clicked the Submit button. A PowerShell window opened and a bunch of results flew past before the window closed itself then suddenly it was done.\nThe next time I saved a file from the browser the dialog was fixed and everything is good with the world.\n\nIf you look close, the default settings turns on a denser mode in the dialog which I really like since I can scan more folder names without having to scroll the list.\nThis utility supports a lot of different options, and I've only played with a few of them so far, but this utility has a lot of power and I'm going to continue to try different settings out.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "First Windows Copilot Experience",
  "date":"Fri Oct 20 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1697846400,
  "url":"/posts/2023/first-windows-copilot-experience/",
  "content":"I've been a GitHub Copilot user since the public beta; a former colleague was a PM on the Copilot team, and I was able to reach out to her directly to get on the beta. Using GitHub Copilot in Visual Studio Code dramatically improves my efficiency writing code, especially for NodeJS or React Apps. I've also been doing a lot of work in Generative AI (GenAI) for my day job at Oracle.\nI get the benefit of GenAI tools in Developer tools, that makes sense to me. Even GenAI in Google and Bing search as well as the command/terminal window makes some sense to me since I'm in that interface while I'm trying to do things. When Microsoft announced Copilot for Windows then automatically installed a pre-release version of it on my Windows system, I really didn't get it. I didn't see (and I still don't see) the need for a chat interface in Windows. I couldn't possibly think of anything I'd want to do with it.\nI knew I could, for example, use Copilot to open Microsoft Word by, you know, typing in Word in the chat interface and letting Copilot open it for me. Unfortunately, I already had an easier way to do that: press the Ctrl and Esc keys simultaneously then type word and press the enter key. Copilot would prompt me to agree that I wanted to open Word, the other approach I just outlined was faster, much faster.\nFast forward to about two weeks ago and I was working on my presentation for the All Things Open (ATO) conference and I came up with the perfect use case for Copilot. My session was about zx and one of my arguments for using zx was for situations where I wrote a shell script (macOS) and command file (Windows) to automate something in one of my development projects that I worked in on macOS and Windows. I knew I'd done that a few times in the past and I wanted to use one of those projects as a case study for my session. Unfortunately, I couldn't for the life of me remember which projects I'd done that in.\nI tried to use Search in a Windows command prompt to find all the folders that contained a .cmd file, but that found all sorts of detritus in the node_modules folders in my Node projects as well. What I really wanted was the way to search for all folders that contained both .cmd and .sh files but I couldn't figure out how.\nSuddenly I had a use case for Windows Copilot!\nI quickly opened up Windows Copilot and typed in the following prompt:\n\nIt responded with:\n\nSigh, that isn't very helpful. One of the few other use cases I came up with related to using Copilot with prompts like &quot;help me find the august-budget spreadsheet&quot; but if Copilot can't view or interact with the file system, it's more than useless.\nNext, started typing out the following response:\n\n\nThis proves that Copilot understood very little of the intent of the prompt I entered.\nNo only did it miss that I wanted only the folders that contained both types of files, it completely missed that I wanted to do this on a Windows system. I asked the question in Windows, why would it give me instructions for linux and macOS and only offer the Windows command option as an afterthought? You'd think Copilot had at least that context; apparently it doesn't.\nEven more evidence that I wanted a Windows response was the fact that the target folder I asked it to start with was a Windows/DOS filepath.\nThinking I could help it out with a more precise prompt (that's the whole point of prompt engineering, right?) I decided to specifically tell it I only wanted folders listed that contained both types of files:\n\nUnfortunately, the response I received back was exactly the same as the previous one.\nI know this is a pre-release feature and I'm glad Microsoft is letting me try it out, but this isn't even pre-release quality. Delivering a chatbot on Windows that doesn't have access to the file system is just stupid.\nAnother issue I have with Copilot is that every time I open it, it hides the Windows taskbar. I don't know if this is on purpose or a bug, but even though I'm entering a chat experience doesn't mean I want to abandon core Windows features (like the taskbar and Start menu).\nThis not a very good start for technology that's supposed to transform the Windows experience.\nPostscript...\nSo I figured I'd complain to it that it didn't understand my question:\n\nAt this point it finally understood me and tried to deliver a useful response:\n\nRunning that code, I finally got the solution I needed.  This is really interesting, I wonder what happened that it suddenly started to understand my question. I personally don't believe that my initial prompts were unclear. I wonder what changed.\n\nLook at that, it seems to work.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "All Things Open 2023 Session Materials",
  "date":"Sun Oct 15 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1697414400,
  "url":"/posts/2023/all-things-open-2023-session/",
  "content":"Tomorrow I'm presenting a session at All Things Open 2023. My session is called Write Shell Scripts Using JavaScript and zx and the session covers how to use Google's zx and Execa to simplify JavaScript scripts that launch external processes.\n\nHere's a link to the slide deck and Source Code.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Developer Tools"
  
  ]
  },

  {
  "title": "IoT Component Manufacturers Ignoring Mounting Needs",
  "date":"Sat Oct 07 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1696723200,
  "url":"/posts/2023/iot-component-mounting/",
  "content":"I'm working on a Halloween project that requires some external hardware components mounted on different things. In this case, it's my Sleeping Dragon in a Mailbox project and I'm trying to figure out how to mount my project's LEDs and mm Wave RADAR devices. Let me explain...\nFor the dragon's eyes (inside the mailbox) I selected the NeoPixel Ring - 12 x 5050 RGB LED with Integrated Drivers. The NeoPixel ring is awesome, but it has some flaws. Take a look at the image below.\n\nFrom a mounting perspective it looks like the person who designed it didn't take into account how the ring would actually be used in a project outside of perhaps sewing it into a piece of clothing.\nThe ring has three required connections, four if you want to connect the ring to other NeoPixel devices. Unfortunately, the solder points for the 4 possible connections are distributed around the ring. This means from a wiring perspective that you must split your wires and spread them around the ring. That works, but it's clunky - depending on the project, you could have these single wires spreading across the project.\nIf you think about how someone like me would use this device in a project, what I want is all of the connections grouped together one one side of the ring. If daisy changing multiple rings together, I'd want the three input connections on one side, and three output connections on the other side, just like they did for the Breadboard-friendly RGB Smart NeoPixel. That just makes more sense.\n\nWith this approach, the wiring is clean, and you can use bundle of wires and keep them together instead of spidering the wires across the back of the ring.\nNow, when it comes to mounting the ring in a project, the designers didn't address that as well. If you're sewing the ring into a project, then you can loop thread across the ring and tie it in that way. But when you're mounting the ring in a project, say for example as Dragon Eyes in a Mailbox, there's no mechanism built into the ring to allow it.\nI used NeoPixel rings in other projects and resorted to using Hot Glue to glue the ring to an enclosure. That works, but it's not sturdy or reliable. The glue could break off at any time leaving my project in shambles.\nWhat Adafruit should have done here was leave an extra border on the inside and/or outside of the ring with mounting holes (and publish the sizes of the holes so customers can easily find the right screw or bolt to use for mounting) to use for, you know, mounting. That should be a requirement for any product - mounting holes.  Make them little nubs (with bolt hole) that can be broken off if not needed.\nEven if you don't want to support mounting holes, at least provide that border so users can cut a groove in a piece of wood or plastic and slide the ring in place.\nA while back, I published an article here about the DFRobot mmWave RADAR device. It's a great device and easy to use (as I described in the article) but now I'm trying to mount it in my project and it looks like my only option is to use Hot Glue again.\nHere's a picture of the board:\n\nUnlike the NeoPixel Ring, it does have mounting holes, but the mounting holes are:\n\nToo small, I can't seem to find screws to use here, unless I go down to less than 2mm.\nRight next to the solder points for the wiring harness.\n\nPutting the mounting holes on either side of the soldered connections only proves that the designer of this board wasn't paying attention to how this board would be used in projects.\nIf I use the bolt holes to mount the board to my project, I lose the ability to solder wires to the board. That makes absolutely no sense.\nDFRobot should absolutely put the mounting holes somewhere else on the board and definitely used 4 holes instead of two as Seeed Studio did with their 24GHz mmWave Sensor - Human Static Presence Module Lite. When you look at the Seeed Studio board, you'll notice that they put mounting holes in the four corners of the board (excellent) plus put wire connections in the middle of the back of the board away from the bolt holes.\nNow, the Seeed Studio board has some issues as well, the wire connections aren't solder points, but at least they gave me a way to mount the board.\nFor either board, another mounting option is to put a little border on the board - don't got for the smallest possible size, add a little room which allows users to slide the board into a groove to hold it in place when bolt holes aren't an option.\nWhat I'm asking for here is Product Designers to actually think about application as well as functionality when designing these boards. Deliver a full and complete product which includes:\n\nAttention to what the device should do (functionality)\nAttention to how the device will mount in a project (application)\nComplete product specifications such as the dimension of the bolt holes (which neither DFRobot or Seeed Studios publish)\nComplete and well documented SDK\n\nTime to go heat up the glue gun to mount the mmWave sensor and LED ring to my project.",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "American Airlines Poor Unsupported Browser Implementation",
  "date":"Fri Sep 22 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1695427200,
  "url":"/posts/2023/poor-unsupported-browser-implementation/",
  "content":"It's been a really long time since I've published a Stupid Developer Tricks post. Aaaah, it feels good to have one again.\nI wife and I flew home from Colorado this week; we vacationed in Telluride and attended the Telluride Blues and Brews Festival. I tested positive for COVID while we were there and delayed our trip home. On the flight home, I decided to watch movies instead of reading books and when I launched the app to access streaming media I received the following message: &quot;Free entertainment is not supported on this browser&quot; as shown in the image below.\n\nI use my iPad every day, but I hate Safari, so my default browser on the device is Chrome. I'm a little surprised by this issue as apparently this works on Chrome on Android. I didn't dig into the details, but I imagine its because of an issue on the iOS side rather than Chrome because Chrome is Chrome.\nAnyway, when you look at the image, notice that the Play button for The Little Mermaid. The Stupid Developer Trick here is that the Engineering team that built this web site knows I'm trying to access &quot;Free entertainment&quot; on an incompatible browser but still decided to give me a button to launch the entertainment.\nIf the browser doesn't support this, the product team should have instructed Engineering to hide or disable the Play button. At the time I was COVID foggy, so I don't remember what happened when I tapped the button, but I think I saw another error message when I did.\nHowever, it makes absolutely no sense to offer users an option you know does not work. As soon as the app detected it was running on an incompatible browser, it should have removed all Play buttons from the page.\nAt this point, the user has to switch browsers, so the next thing that should happen is the app should help the user do that.\nOne option could be to launch Safari on behalf of the user, but I'm not sure a web app can do this. In this case, the American Airlines app opened the browser window, so why didn't the app open Safari instead of the default browser? That would be an easy fix, right?\nAnother option is to give the user a button to copy the page URL to the clipboard to save some steps when they get over to Safari.\nI'm just so surprised because American Airlines has a pretty good app and web sites. It feels like nobody took the time to think about how users act or what users need in this case.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Glowing Pumpkin Project Refresh",
  "date":"Tue Aug 29 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1693353600,
  "url":"/posts/2023/glowing-pumpkin-project-refresh/",
  "content":"Years ago I published a several Glowing Pumpkin projects: Arduino Glowing Pumpkin and Arduino Glowing Pumpkin (Adafruit Feather). Both projects used Arduino compatible devices plus either one of the Adafruit multi-NeoPixel devices or a NeoPixel shield. The shield approach was easy because I just had to solder some male and female headers to the boards and press them together into a unit. My first project used the NeoPixel Ring which required soldering wires and running them into an enclosure where the Arduino device resides.\nI always wanted to redo this project, especially using some of the smaller ESP32 devices like the Seeed Studio Xaio series of microcontrollers. A while back I was perusing the Adafruit site looking for new products when I noticed the Adafruit 5x5 NeoPixel Grid BFF Add-On for QT Py and Xiao; it's a super tiny device, designed to attach back to back with a Seeed Xiao board. This combination gives me an opportunity to do a super small reboot of the glowing pumpkin here.\nI updated the code and published the project today in Glowing Pumpkin Xiao 5x5 BFF. This version is the size of the tip of my thumb and uses the powerful ESP32 processor so I can do some pretty interesting things using a web server with remote control from a mobile app or web browser. Eventually, I plan to synchronize LED matrix colors across multiple devices which enables me to put these devices in pumpkins in each of the dormers in front of the house and have them all display the same colors.\nHere's the project in action:\nhttps://youtu.be/05cMcB_vGCM\nAnd here's the original project (on the right) and the latest version on the left. See how much smaller the new version is? And its much easier to assemble.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Arduino ESP32 Web Server on a Processor Core",
  "date":"Sat Aug 26 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1693094400,
  "url":"/posts/2023/arduino-esp32-web-server-on-a-processor-core/",
  "content":"I wrote the Arduino ESP32 Running Tasks On Multiple Cores post I published earlier this week so I could publish this one.\nYears ago I published a several Glowing Pumpkin projects: Arduino Glowing Pumpkin and Arduino Glowing Pumpkin (Adafruit Feather). Both of them used Arduino compatible devices plus either one of the Adafruit multi-NeoPixel devices or a NeoPixel shield.\nI always wanted to redo this project, especially using some of the smaller ESP32 devices like the Seeed Studio Xiao series of microcontrollers and some of the smaller NeoPixel matrixes like the Adafruit 5x5 NeoPixel Grid BFF Add-On for QT Py and Xiao. Because of this, I recently published a refresh in Glowing Pumpkin Xiao 5x5 BFF.\nWith that project in the can (a movie-making term) I started thinking about what else I could do with it. I quickly realized that I could enhance the project by adding a web server and letting a user remotely control the pumpkin illuminating hardware using a web browser or mobile app. I agree that that's not the most interesting use case, but I figured I'd use what I learned about splitting tasks across multiple ESP32 processor cores to run a web server on one of the cores while the other one does something else.\nThis article explains how I did it. If you want to skip the explanation all together and jump to the code, you can find the complete project code at Glowing Pumpkin Xiao 5x5 BFF Server.\nThe API\nFor this project, I have this Arduino compatible Microcontroller with a 5x5 NeoPixel matrix strapped to its back residing NeoPixels facing up inside a theoretical carved pumpkin. What would I want to be able to do with this thing?\nAssuming the following NeoPixel configuration:\n\nI came up with the following API:\n\n\n\nMethod\nDescription\n\n\n\n\n/color:#\nLights all of the NeoPixels with a specific color. The command accepts a single parameter, the array index for the selected color. So, for example, to illuminate all of the LEDs Purple, the command is color:3 as Purple is the 4th color in the array (with an index of 3 since C arrays start at 0). To illuminate the LEDs Blue, the command is color:0.\n\n\n/flash:#:#\nFlash the LED matrix a specific color a specific number of times. For example, to flash the LED matrix Blue three times, the command is flash:0:3.\n\n\n/lightning\nFlash the LED matrix White a random number of times for a random amount of time for each flash in an attempt to simulate lightning or electrical flashes inside the pumpkin.\n\n\n/off\nTurns off the LED Matrix (sets all NeoPixels to CRGB::Black).\n\n\n/random\nEnables random mode where the ESP32 device randomly picks a color from the array and displays it for a random amount of time (seconds) before picking another color and starting all over again.\n\n\n\nCORS Impact\nBefore I get too far into this post I have to warn you about something.\nEven though you can run a Web Server on an Arduino device and have it process requests, it doesn't mean that you can access the web server from any device anywhere. The Internet, well, really mostly Google, conspires against you and will block responses from the web server in several scenarios.\nYeah, I know, right?\nAnyways, back in 2019 Google got serious about HTTPS requests vs. HTTP; you can read about it in No More Mixed Messages About HTTPS. With this, Google started preferring HTTPS connections (while still allowing HTTP connections) but eventually started blocking HTTP connections all together.\nThere's also this thing called Cross-Origin Resource Sharing (CORS) that tries to help secure connections between a browser and a server. The web application has to enable CORS (which basically means adding some headers to the request) in order to be able to make a request to the server and the server must respond in kind (with the right headers). Even if you setup CORS correctly, the browser will block responses from our tiny little web server unless:\n\nThe web server and the system running the browser are running on the same local network.\nYou use some other application other than a browser to connect to the web server.\nYou're using an Internet-hosted web application, but set some special settings that allow the browser to connect to the server and accept responses from it.\n\nI know, it's a pain in the @ss.\nSo, for this post, I cover the web server code in detail; in the following article I'll explain all the options for accessing the web server from a variety of devices and tools. I apologize for that, but this article is going to be pretty big without me covering all options.\nAs you look through the code for the web server, in most of the request handlers you'll see the following in the code:\n\nThe code exits the function if the incoming request is not an HTTP GET request. I had to add this because with CORS enabled, the browser sends a pre-flight check request to the server first to see if it can handle the request. Only after the web server responds to that request will the browser send the actual request.\nThe side-effect of this is that th",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino",
  
    "ESP32"
  
  ]
  },

  {
  "title": "Arduino ESP32 Running Tasks On Multiple Cores",
  "date":"Thu Aug 24 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1692921600,
  "url":"/posts/2023/arduino-running-tasks-on-multiple-cores/",
  "content":"I've been coding and building on the Arduino platform (both hardware and software) for a long time. Looking back on this site, I see that I created my First Arduino Project back in 2014, almost 10 years ago.\nOver the years, microcontrollers got more capable with faster processors, more memory, and, happily, multiple processor cores. I always wanted to learn how to split tasks across multiple processor cores in an Arduino project, but every time I tried following one of the tutorials I failed. Another issue, for me anyway, is that many of the tutorials were so full of advertisements, that it was too distracting to use them.  What I wanted was to be able to look at a small, simple but complete, example of how to do what I wanted to do.\nAfter failing several times, I finally found some time to dedicate to making this work and quickly succeeded. You can find the complete code for this project in Arduino ESP32 Multiple Cores.\nFor this project, I used a Seeed Studio Xiao ESP32 device. I picked the ESP32 because it's multi-core (a requirement for this project), very small, and very inexpensive.\nWasting no more time, lets get into the code...\nThe ESP32 libraries for Arduino include a task handle type: TaskHandle_t. Using a task handle, your Arduino project points to a block of code (a function) you want executed on a specific core then assigns that code to the specified core. Note: I've not studied the code, that's just my simple layman's view of how this works.\nSo, to assign code to separate processor cores, you create one or more task handles like this:\n\nNext, the sketch uses the xTaskCreatePinnedToCore method to assign the appropriate code to the selected processor. Since the sketch only needs to do this once, add the calls to xTaskCreatePinnedToCore to the setup function in the sketch as shown below.\n\nThe xTaskCreatePinnedToCore method is an ESP32-specific method (apparently not part of the FreeRTOS the ESP32 runs) provided by Espressif (the makers of the ESP32 device). You can read more about it in the Espressif documentation.\nThe following table describes the parameters passed in the call to xTaskCreatePinnedToCore.\n\n\n\nParameter\nDescription\n\n\n\n\npvTaskCode\nThe name of the function that contains the code you want running on the assigned processor core.\n\n\npcName\nThe friendly name for the task\n\n\nusStackDepth\nThe amount of bytes allocated for the task stack. I don't know how to allocate this, so I just use 10000 which I've seen in several examples.\n\n\npvParameters\nA pointer pointing to any parameters you want passed to the task code.\n\n\nuxPriority\nThe task priority; I always use 1 across all tasks, but if you have long-running tasks with different priorities, you can tune how much attention they get by playing around with priority.\n\n\npvCreatedTask\nA pointer to the task the sketch can use to reference the task later (for example to terminate it).\n\n\nxCoreID\nThe processor core to assign the task to.\n\n\n\nSo, taking a look at this line of code from the example:\n\nWhat's happening is I'm taking a function in my sketch called Task0Code, giving it the human-readable name of Task0 with a stack of 10k bytes and a priority of 1 then assigning it to run on processor core 0.\nIf you've worked with Arduino for a while, you're used to putting your code that runs as long as the device is powered-on into a function called loop:\n\nIn this case, my sketch has two blocks of code, and I'm assigning each block of code to a separate processor core, so I really don't need to do anything in my loop function. To prove that the code in the loop function executes as well as the code I assigned to the different processor cores, I added a little delay and wrote some text to the Serial monitor:\n\nOK, now everything's setup. All that's left to do is show you the code that runs on the processors. Here's an example for the code assigned to processor core 0:\n\nNotice the pcParameters in the function declaration, this is the variable that receives the pointer to the parameter object passed during core assignment. If you had a long-running task you wanted to fire up for different actions in your sketch, you could fire up a task, pass in the parameters needed to tell the task's code what to do, then destroy the task when its done. In my example, I didn't need to do that, so I pass no parameters to the task.\nAt the top of the function is some code that writes some text to the Serial Monitor letting me know what processor the task is running on. This code executes once, when the sketch assigns the task to the processor, so you'll only see the Task0 running on core 0 message once in the Serial Monitor.\nThe next piece of code is critical to getting this to work correctly for this scenario:\n\nIt defines an infinite loop (remember, replacing the loop method in the main sketch) that does whatever this task is supposed to do on the assigned processor. In this case, I simply write some text to the Serial Monitor then wait a random amount of time before doing it again.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "ESP32",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Gihub's Fake 2FA Warning",
  "date":"Mon Aug 07 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1691452800,
  "url":"/posts/2023/gihubs-fake-2fa-warning/",
  "content":"Why exactly is GitHub warning me that I must use 2FA for my account when I already have it enabled (and have had it enabled for years)? End of post.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Simple RPN Calculator",
  "date":"Sun Aug 06 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1691366400,
  "url":"/posts/2023/simple-rpn-calculator/",
  "content":"On my 18th birthday, my high school girlfriend gave me an Hewlett Packard 41CV calculator; I loved that thing. Owning it introduced me to Reverse Polish Notation (RPN) as well as extensible computers. It wasn't a calculator, it was a programmable computer you could hold in your hand and I programmed the hell out of that thing. It allowed you to plugin modules, I think it had 4 slots and I had a whole bunch of modules. This thing was even something they used to calculation on the space shuttle: Calculator, Hand-held, HP41.\nThat particular device is long gone and I've burned through a couple of replacement devices over the years. I can use a traditional calculator, but I do much better with RPN-based ones. I've played around with the different RPN calculators on Android and iOS, but none of them meet my needs.  I have one on Android that's excellent, but so many of these app developers try too hard to mimic the layout and look of HP Calculators, so for this particular one, I can never seem to find the X&lt;&gt;Y button when I need it.\nAnyway, I drew out a wireframe diagram of the app's UI (see below) and I've open sourced the code so you can follow along as I build this thing. No guarantees for when I'll finish this thing, but I have some time over the next few weeks to dedicate to this, so it may not be too long. You can find the code in Simple RPN Calculator.\n\nI'm writing the app using Flutter for a variety of reasons:\n\nI LOVE writing Flutter apps\nUsing Flutter allows me to deliver mobile apps as well as a web application. I can even build this thing for Windows and macOS so I can run the app anywhere.\nDid I mention that I LOVE writing Flutter apps?\n\nStay tuned on this one, I'l share real app screen shots when I make real profgress.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "Miscellaneous",
  
    "Flutter"
  
  ]
  },

  {
  "title": "Eleventy Category Images",
  "date":"Thu Aug 03 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1691107200,
  "url":"/posts/2023/eleventy-category-images/",
  "content":"When I built this site, one of the features I wanted in the site was displaying a custom header image based on the category in a post or one of the Category pages. I had a lot of different ideas how to do this, but I wanted to make sure that the solution I picked was easy to manage and added the smallest amount of overhead to the site.\nIn my A World Without Apps site, I decided to grab the header image file from a folder based on the first category name:\n\nThat worked really well, and was easy to setup, but the alternative text was a little lame, simply using the category name plus the word 'image'. The images I used are from Unsplash, so I needed a way to display an image attribution at the bottom of the page, but the approach I took was really ugly as shown below:\n\nI'm embarrassed of that solution; as I add categories to the site, it simply becomes much more difficult to manage.\nWhat I really need is a data source I can use to manage the category image file path, alt text, and attribution; something like this:\n\nDue to Eleventy's excellent data management system, I could create and maintain that file, then pull in the different properties when rendering a page during the build process.\nI'm lazy, so I don't want to create and maintain that page. Fortunately, a while back I created the eleventy-generate-category-pages module that creates and maintains a category data file in my Eleventy site automatically (during the build process). Here's the categoryData.json file from this site. All I had to do was add the header image properties to the data file and I'd have a permanent place for my category image file properties.\nTo accommodate this, I added a new configuration option for the category pages module called imageProperties and it adds the imageFilePath, imageAltText, and imageAttribution properties to the category data file automatically. To enable the option, just add the imageProperties option and set it to true when loading the module in the site's eleventy.config.js file:\n\nWith that in place, the category data file now looks like this (with most of the categories removed):\n\nThat makes this whole process really easy for me as the module adds new category objects to the file when I add a new category to the site. If I edit posts and remove references to the category, it automatically removes the category object from the data file.\nNow, all I have to do is use the data file to add the necessary img tag and attribution to the site. To do this, I added two custom shortcodes to the site: CategoryImage and CategoryAttribution. You can see them in use in the following code. My site lets me set a header image per post, so the code tries to load that image first, but if there isn't one, it grabs the first image and alt text it can find for the list of categories assigned to the post; I'll show you that code in a minute.\n\nAfter the post content, the code pulls in the header image attribution (if there is one assigned) otherwise it pulls in the attribution from the category data file using the same algorithm from the header image described above: it loops through all of the categories assigned to the post and grabs the image attributes from the first category entry that has them.\nYou can find all the code for the two shortcodes in eleventy.config.headerimage.js. You can use this as a template for your site, replacing my code that generates img and p tags with whatever code is appropriate for your site's configuration, layout and styling.\nI kept all of the code in a separate file so I can reuse it for other sites I maintain. Notice that when I load the module, I pass in the name of the category data file (it could be different depending on the site) as well as the style to apply to the generated image tag (which will vary depending on the site).\n\nIt was a lot of fun to put together this solution, I hope you find this useful and can use it for your sites. I'm trying to decide if I should make this more flexible by passing in the template strings to use for the img and p tags, that wouldn't be hard to do and would make it easier to copy the code from project to project without modifying the source. I may make that change and add the eleventy.config.headerimage.js image file to the module in a future release. Let me know your vote on this.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "DFRobot mmWave RADAR",
  "date":"Sat Jul 15 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1689465600,
  "url":"/posts/2023/dfrobot-mmwave-radar/",
  "content":"A couple of months ago, I started planning my Halloween project for this year. In previous years I've created a Candypult (for the pandemic years), a remotely controlled flame breathing pumpkin (Sparky, we call him), and, my favorite, the twinkle light tubes from last year.\nThis year I'm making a sleeping dragon. The first step for this project is to make an interactive lighted sign. I reached out to a designer I've used on Fiverr and he quickly drew this up for me:\n\nNext, I sent the design to the folks at Ponoko to have them LASER cut the design on some acrylic. Finally, I wired up a Microcontroller to some NeoPixels to illuminate the sign.  I'll write more about the sign hardware after I've built an enclosure for it.\nWhat I want to do with this project, or at least this part of it, is illuminate the sign a certain way by default, but flash the NeoPixels differently when someone is nearby. I originally thought I'd use a PIR Sensor for this, but then I started reading about mmWave sensors that can detect humans and I realized I just had to use one for this project. A sensor like this should be able to distinguish between humans and other things (like dogs), so that would make this project... better.\nDFRobot offer a mmWave Radar - 24GHz Human Presence Detection Sensor (9 Meters) that seems perfect for this project and the folks at DFRobot were kind enough to provide me with one to evaluate.\nThe sensor communicates with a microcontroller (or whatever you want to connect it to) using a serial interface, so you'll need to connect power (V+ and GND) as well as transmit (TX) and receive (RX) connections. Here's an image of my POC configuration:\n\nTo use this sensor, you face the antennas toward the detection area and the SDK offers multiple options for configuring detection range and more. The device was really easy to wire into my project; I'll show you the full hardware build out for this closer to Halloween. Installing the required library and getting it working was very easy as well.\nHere's the code I used to validate the sensor's operation, I'll explain the code and more after the code.\n\nThe hardest aspect of this for me was configuring serial communication with the sensor. I'd never user serial communication to talk to a sensor before, so I was unfamiliar with HardwareSerial (and its sibling SoftwareSerial).\nApparently, due to microcontroller hardware configuration, some boards can support multiple Serial connections. Those devices use HardwareSerial to talk to the embedded serial communication hardware. For those devices that don't have the required hardware, use SoftwareSerial instead.  Once I sorted out that the board I used, the Adafruit ESP32 Feather V2 had the required hardware I was all set.\nThe code starts by defining a hardware serial port then initialized the mmWave library to use it:\n\nIn setup(), reset the device to factory settings, then configure the detection range (3 meters in this case) and output delay time:\n\nOutputLatency controls how long the sensor waits after detecting something and how long after the person leaves detection range before the sensor notifies the application:\n\nIn this example, it waits 2 seconds before notifying the app and waits two seconds after it leaves detection range before telling the app that its gone.  This allows my project to wait a bit before reacting.\nIn the loop, the code reads the sensor, turns the microcontroller's onboard LED on or of depending on whether it detected a human or not (options are basically HIGH (detected) and LOW (not detected)).\n\nHere's a Gist of the code.\nThat's basically it, the sensor is very easy to integrate in projects and really easy to code to as well. The documentation is complete and very good as well. I'll show you the complete project and code closer to Halloween.\nOne thing I didn't like about the sensor is that it has an Onboard LED that illuminates when it detects something. I understand why DFRobot would add this to the sensor, so user cn tell its working, but for my particular project, I don't want that. DFRobot didn't include an option for disabling the LED in the SDK; I hope they do so in a future update. I will likely cover the LED in my project.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "AI Developer Tools in Action",
  "date":"Fri Jul 14 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1689379200,
  "url":"/posts/2023/ai-developer-tools-in-action/",
  "content":"Note: This article cross-posted from A World Without Apps.\nA while back, I created a plugin for Eleventy web sites; Eleventy is a static site generator I use for this site and several others. The plugin calculates some simple statistics from the articles in the site, you can see the plugin in action on johnwargo.com.\nOne of the features I've been wanting to add to the plugin is article word, paragraph, and code block counts. My wife is out of town this weekend and my kids work, so I have some extra time this weekend to work on this. I've been a little nervous about these new features because I know I need to use Regular Expressions (RegEx) and I'm not an expert in Regular Expressions. Since the project is open source, free to use by anybody, I knew that my code could get some scrutiny so I wanted to write clean and efficient code.\nI read a primer on RegEx in JavaScript and learned quite a few things I didn't already know. Next, I started Visual Studio Code, opened the project, then opened the project's main code file. I opened up some space in the code to add a new function and started typing.\nI decided to start with the code that counts the code blocks in the article/post since I figured that would be pretty easy. Article code blocks start with &lt;pre&gt; and end with &lt;/pre&gt;, so I knew exactly how to count them programmatically.\nI started typing the function declaration:\n\nAs soon as I did, the AI-based tooling I have installed in Visual Studio Code (I wrote about them in Coding One-handed) immediately finished the declaration for me:\n\nThat is exactly right; I expected to pass in the post content as a string, so that works so far and the tooling saved me a little bit of work. When I accepted that proposed code, the tooling then suggested the complete function code I needed to complete the task:\n\nLooking at it, I saw that it was exactly the code I needed to complete the task. It should work but I've not tested it yet, I immediately wrote this post when it happened.\nNow, looking at the code some more, I realized that there is one small change I need to make. The AI-based tooling suggested JavaScript code for me, but this particular project uses TypeScript (a superset of JavaScript), so I had to make one small change to make the code perfect; setting a return type of number.\n\nThe code should work either way, but this is a very good example of the developer efficiencies delivered via AI-based developer tooling. What I expected to take minutes to figure out only took seconds, imagine what this does to developer productivity.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Developer Tools",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Added Content Stats to Eleventy Plugin Post Statistics",
  "date":"Fri Jul 14 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1689379200,
  "url":"/posts/2023/added-content-stats-to-eleventy-plugin-post-statistics/",
  "content":"When I created the Eleventy Plugin Post Statistics plugin, my plan was to include post content statistics as well (character, word, paragraph counts and more). Unfortunately, I encountered an error in the Eleventy build process whenever I tried to access the post content; Eleventy simply doesn't allow it.\nThe plugin was functional, so I released it expecting that I'd add support for content statistics later. I recently picked the plugin work again, migrating the plugin to TypeScript and adding some little features. Today I decided to tackle post content stats and I got it working.\nI couldn't get around Eleventy's issue with throwing an error every time I tried to access post content using the collections API, so I decided to read post files directly and calculate the content statistics that way.\nWhen looping through the posts in a site, Eleventy tracks the post.page.inputPath property which is the relative path to the selected post. Once I had access to that, I simply opened the file directly (using node's fs.readFileSync method) and tore through the content.\nThe plugin delivers a lot more data now:\n\nI also updated the sample statistics page in the plugin repository (and this site) to display all the new data:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Batching YAML Front Matter Updates",
  "date":"Sun Jul 09 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1688947200,
  "url":"/posts/2023/batching-yaml-front-matter-updates/",
  "content":"When I migrated this site from Joomla! to Eleventy, I realized about halfway through the process (after migrating 400 or so articles to .md files) that I wanted to include a description property in articles through YAML front matter properties. This description value became the description for the article in site list views and I also use it to set the description meta tag in the page's HTML Head.\nFor example, here's the front matter for this post:\n\nHere's the description on the home page:\n\nAnd here's the description meta tag:\n\nSo, now that you know why I wanted to add the description property to all of my site's articles, the question is how to add it to every article.\nNow, I knew I'd have to write the description for each article, but that generally means copying the first paragraph from the article and editing it. What I needed was a simple way to add the property to the front matter, then I can go back in and start copying the content in. For other use cases, I could add a property and value at the same time, even overriding existing values in the process.\nI decided to build a command-line utility to do it for me. The utility I created is called YAML Add Property and you can find it on npm.\nYou can use it to:\n\nAdd empty properties to YAML front matter\nAdd properties and values to YAML front matter\nUpdate existing front matter property values.\n\nTo execute the utility, open a terminal window or command prompt, navigate to the Eleventy project folder (it doesn't have to be an Eleventy project), and execute the following command:\n\nThe module will prompt you for the operational parameters to use while executing:\n\n\n\nPrompt\nInput\nDescription\n\n\n\n\nSource folder\nString\nThe folder name, relative to the execution folder, for the source files.\n\n\nProperty name\nString\nThe property name added to the YAML front matter.\n\n\nProperty value\nString\nThe value assigned to the property added to the front matter. When omitted, defaults to a blank string ('')\n\n\nOverride existing\nYes/No\nControls whether the package overrides the property value if the file already has the property in its front matter.\n\n\nProcess subfolders\nYes/No\nControls whether the package recurses through sub folders when building the file list\n\n\n\nTo display additional information in the console during execution, enable debug mode by adding a -d to the command line.\nWhen the command executes, it will update the console as shown in the following figure:\n\nI hope you find this utility helpful.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Developer Tools",
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Updated Eleventy Post Stats Plugin",
  "date":"Thu Jul 06 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1688688000,
  "url":"/posts/2023/updated-eleventy-post-stats-plugin-/",
  "content":"I published an update to my Eleventy Plugin Post Statistics plugin today. I intend to add post paragraph count, post word count, and, perhaps, post code block count to the plugin, so this version sets everything up for that work.\nChanges in This Version\nChanged count to postCount\nOne of things I noticed after I published the plugin is that I erred in naming the post count property in the JSON object generated by the plugin. As you can see in the original example, I called the property count when I really should have called it postCount to be more clear in what/which count is reflected in the data.\n\nIn today's release, I changed the property name to postCount as shown below:\n\nThis is a breaking change, so in any pages that display data generated by the plugin, you must change all references to count to postCount like the following examples from the plugin's sample index.liquid file:\n\nThe following displays the generated data in table format:\n\nBecause of the breaking change, I incremented the plugin's minor version number so existing Eleventy projects will continue to use the older version until you manually upgrade the plugin in your project(s).\nDebug Mode\nI wanted to understand how to add configuration options to an Eleventy plugin, so I added a debugMode option that outputs just a tiny little bit more output to the console when the plugin executes.\nTo enable debugMode, change the plugin installation code in your project's eleventy.config.js to the following:\n\nI plan on adding new features to the plugin, so I expect to add more options to the options object over time. Stay tuned on that one.\nTypeScript Conversion\nFinally, I converted the project to TypeScript because, well, I wanted to. I enjoy the developer efficiencies I get by using TypeScript, so I converted the project. It only took me a few minutes and now future enhancements will be easier.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Eleventy Filter Parameters",
  "date":"Tue Jul 04 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1688515200,
  "url":"/posts/2023/eleventy-filter-parameters/",
  "content":"I hate it when software products and sites publish large numbers (greater than 1,000 - notice the comma?) without using thousands separators and the like. When I built the Statistics page, I made sure to add a commaize filter to ensure my site stats larger numbers displayed the correct punctuation:\n\nWith that in place, as I displayed statistics on the page, I'd comma-ize the values like this:\n\nThis works really well, but renders all numbers using the English US locale (en-us) which is fine for this site, but hard-coded. I also wanted to understand how to use parameters with an Eleventy filter. With that in mind, I made an update to the filter, adding an optional parameter I could use if I wanted to format a number using a different locale (I don't, but this is just an exercise).\nTo do this, I added a locale parameter to the commaize filter's function and gave it a default value as shown in the function signature below:\n\nNext, I use the passed locale (or default value) as input to the toLocaleString method. With this in place, the filter defaults to English, so the following Liquid code renders to 1,024:\n\nHowever, if I want to render the number with another locale's formatting, like Portugal (por) for example, I can pass the locale parameter to the filter as shown below:\n\nThis renders the number as 1.024 (which is the Portuguese way of doing thousands separators).\nAnd now I know how to add an additional parameter to an Eleventy filter.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Coding One-Handed",
  "date":"Mon Jul 03 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1688428800,
  "url":"/posts/2023/coding-one-handed/",
  "content":"I had shoulder surgery just about a month ago. Surprisingly, I had very little pain, so I went back to work much earlier than expected. Not being able to do much, I spent my free time migrating a couple of WordPress sites to Eleventy. Typing one-handed is cumbersome, but I got good at it and got a lot of work done.\nHaving gotten caught up on my web development tasks, I started on another project. I keep all of my personal mail in Outlook, and archive anything older than a year old to an archive file. I noticed recently that because of this archiving process I had a bunch of empty folders in my inbox. Having done a fair amount of Outlook automation in the past using Delphi I thought I'd write a quick little utility to delete all of those empty folders.\nI fired up RAD Studio (the IDE for Delphi) and started copying in a bunch of code I found on the Internet and quickly found that it was really hard to code in RAD Studio one-handed.\nNow, you need to understand something about me. I started coding in Turbo Pascal back in the 80s; I even had a CP/M card in my Apple //e so I could run Turbo Pascal. When (then) Borland released Delphi 1.0 (1995), I immediately ordered a copy and have owned a license (with many, many upgrades) ever since. Until I started building mobile apps, all of my commercial software products (including one IBM sold worldwide) were written in Delphi. I've written a lot of Pascal code in Turbo Pascal and Delphi editors, of any compiled language I've worked in, this is the one.\nFor me to say it was really hard to write some Delphi got me thinking: Why was it so hard to do one-handed? As I explained in the previous paragraph, I'm kinda an expert in Delphi, why would it be so much harder?\nIts the tooling.\nI do most of my coding in Visual Studio, as much as I can. I own licenses for WebStorm and PyCharm, but I rarely use them. In Visual Studio, I've installed a bunch of plugins that really make my one-handed coding life easier. The two most important for me are IntelliCode and GitHub Copilot.\nThe two work together to eliminate a lot of the coding work I do.  I knew Copilot was awesome (I was a Beta user and pay for a license today) and I'd forgotten about IntelliCode running in there, but with them in there as I work on a project, they both make really accurate suggestions and, when I accept them (which I usually do), it dramatically cuts down on the work I do.\nOne of the things I like about it, and I think its IntelliCode that's doing it, is that many of the recommendations I get are in my coding style. IntelliCode apparently looks how I did similar things previously and suggests things in the same coding style. How cool is that?  I knew I had my own style, I wasn't expecting the tooling to pick up on my style and parrot it back to me.\nI hadn't thought about how much these tools help me until I used an IDE that didn't have AI helpers. The difference is mind-boggling.\nI put aside my Delphi work, as its just too hard to do right now. Perhaps I'll pick it back up again when I have two hands at my disposal.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Developer Tools"
  
  ]
  },

  {
  "title": "Updated Eleventy Generate Posts Utility",
  "date":"Fri Jun 30 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1688169600,
  "url":"/posts/2023/updated-eleventy-generate-posts/",
  "content":"When I created the Eleventy Generate Posts command-line utility, I configured the command to expect all of its configuration parameters on the command-line. I did this thinking it would be simple to use, but weeks later I already forgot which command-line options I needed in what order.\nI migrated a couple of Wordpress sites to Eleventy using the wordpress-export-to-markdown and that utility does an excellent job prompting for all of its configuration options. With that in mind, I decided to do the same thing with my 11ty-gp utility.\nWith this version, just published, you can execute the utility using:\n\nnpm will pull down the utility and execute, prompting you for the information it needs to execute as shown below:\n\nConfiguration options are:\n\nPosts Folder: Relative path pointing to the Eleventy project's posts folder; use . for the current folder.\nNumber of Posts: An integer value between 1 and 100 representing the number of posts generated.\nPost Tag: The front matter tag property applied to the generated posts\nStart Year: The starting year used for post date in the generated posts. The command uses the current date or the current date with the specified year (when provided) to for the post date for the first generated post. For subsequent post dates, the command randomly decrements the day.\nYear Mode: Specifies whether the module writes generated posts to the Posts folder (N) or into a separate folder for each year (Y).\n\nObviously if you generate enough posts to push into the previous year, the posts will save into a folder for the previous year.\nTo enable debug mode, pass a -d flag on the command-line; in this mode, the module writes additional information to the console as it executes.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "All Things Open 2023 Speakers",
  "date":"Thu Jun 22 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1687478400,
  "url":"/posts/2023/all-things-open-2023-speakers/",
  "content":"I was looking at the All Things Open 2023 - First Round Speakers page the other day and noticed my name and picture there, how cool is that?\nHere's my speaker profile.\nI can't wait for the conference; this will be my third time presenting at this amazing conference.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Events"
  
  ]
  },

  {
  "title": "Fixed Category Page Generation",
  "date":"Tue Jun 13 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1686700800,
  "url":"/posts/2023/fixed-category-page-generation/",
  "content":"In Generating Eleventy Category Pages Inside Eleventy Build I described how I was trying to migrate my Eleventy Paginated Category Pages command line tool to run inside of the Eleventy build process.\nThe module is Eleventy Generate Category Pages and I published it to npm today.\nTo use it in you Eleventy projects follow the instructions in the project repository, but basically:\nInstall the module in your Eleventy project using:\n\nCreate a before event handler in your project's eleventy.config.js file using the defaults:\n\nor, specifying specific settings for your project:\n\nFinally, Create a template file for the generated paginated Category pages, you can find an example template in this site or in the module's readme file.\nPostscript\nAfter publishing this post, I realized that I created an infinite loop when running Eleventy with the --watch or --serve flags. Eleventy would generate the category pages then build the site, but whenever I made a change to the site, it would generate the category pages again which, of course, caused the site to generate itself again. Sigh, creating an infinite loop is never fun.\nAnyway, I updated my code to force it to only run once in this situation using the following code:\n\nThis works quite well!\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Hiatus",
  "date":"Mon Jun 05 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1686009600,
  "url":"/posts/2023/hiatus/",
  "content":"Taking a Hiatus\nBeginning June 7th, 2023 I’ll disappear for a while and I’m not sure how long I’ll be gone. I’m having shoulder surgery and my arm will be immobilized for at least six weeks, perhaps more. My wife volunteered to type for me while I’m out of commission, so we’ll see if I can make that work if something comes up I want to write about.\n\nPhoto by Inge Poelman on Unsplash.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Generating Eleventy Category Pages Inside Eleventy Build",
  "date":"Sun Jun 04 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685923200,
  "url":"/posts/2023/generating-eleventy-category-pages-inside-eleventy-build/",
  "content":"Last week I published an article, Eleventy Paginated Category Pages, that described a command-line utility I created that runs as a preprocessor to the Eleventy build process and generates paginated category pages for every category in use in an Eleventy site.\nI wrote it as command-line tool because I didn't know how to build something like that and inject it into the Eleventy build process. I expected that I should be able to publish it as a Node module and call it from the build process, but I didn't want it to be clunky.\nA few minutes after I published the article, I finished reading Eleventy by Example and found the answer I needed there. I wasn't aware of the Eleventy build events and the book showed me everything I needed to know to execute the module before Eleventy starts its build process like this:\n\nSo, that afternoon I created a new Node module project on GitHub called Eleventy Generate Category Pages and pulled into the project the guts of the command line utility into something you can execute during the before event.\nIt works great as far as I can tell in my tests, but I wrote the original module in TypeScript and I'm in module hell trying to get this generated code to run in an Eleventy project. This isn't something I can't figure out, but as you'll see in tomorrow's post, I'm getting shoulder surgery on Wednesday and I don't have time to fix this issue before then.\nThe issue is getting the right settings in the project's tsconfig.json file so it will execute properly in an Eleventy project. Its not rocket science, I just don't have the time right now to experiment with different settings.\nI'll get to fixing this as soon as I can, but I'll be without use of my left hand for almost two months, I don't expect to do a lot of coding while I'm recovering. If someone in the community wants to fix this, I'll make sure I check for pull requests as often I can.\nLooking for the community's help.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Eleventy Paginated Category Pages",
  "date":"Tue May 30 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685491200,
  "url":"/posts/2023/eleventy-paginated-category-pages/",
  "content":"One of the features many content management systems (CMS) give users is the ability to generate paginated lists of posts/articles as well as a way to display a paginated list of all posts in a particular category. Static site generators like Eleventy deliver pagination capabilities which allow you to generate pages that break up a list of items into batches on each page.\nEleventy has a limitation in that you can use its pagination feature to generate a separate page per category (which then lists all posts in the category) or pages which display a paginated list of posts for a particular category, but not both. What I want for this site is for Eleventy to generate separate pages for each category as well as to paginate the posts on each category page, something I call Nested Pagination (or paginated paginating pages). Eleventy can do it, just not automatically.\nEarlier this year, I published an article that shows how to generate a simple page of categories for a site: Eleventy Site Categories Page, that's not hard. What I'll show in this post is how to link that categories page to a separate set of pages for each category with pagination for the post listing.\nTo deliver what I want here, I could manually create a separate page for each category using the Eleventy pagination feature to display the posts in batches. Unfortunately, I don't want to do that because that means manually managing the category pages, creating a new one every time I add a new category for the site, and deleting pages when a category goes out of use.\nTo solve this problem, I created the Eleventy Category Pages preprocessor module (find it on GitHub and npm). You can see it in use in this site at Categories.\nNote: After posting this article, I finished reading Eleventy by Example and I now see how I can make this an Eleventy plugin instead of a stand-alone utility. I'll start work on converting this to a plugin; stay tuned.\nThe module essentially does two things:\n\nGenerates a global data file containing metadata about all the categories used in the site. You'll use the file to generate links to all the category pages in your site.\nGenerates a separate page for each category used in the site with pagination for the posts in the category. These pages display all of the posts for the particular category.\n\nIn the rest of the article, I’ll walk through all of this and show you how it all works.\nInstallation\nThe method you use to install the module differs depending on whether you want to run the preprocessor from a command-line or as part of an external build process or whether you want to execute it as part of the Eleventy site build process.\nGlobal Installation\nWhen you install the module globally, any process on the system can access it, for example if you want to execute it from the command line or as part of an external (to Eleventy) build process. To install the module globally, open a command prompt or terminal window and execute the following command:\n\nThis creates a 11ty-cat-pages command you can execute from anywhere on the system.\nLocal Installation\nIf you want to run the module as part of the Eleventy site generation process, you’ll install the module in the Eleventy project and add module execution to the site’s package.json as a build task. To do this, open a terminal window or command prompt, navigate to the eleventy project’s root folder, and execute the following command:\n\nThis creates a 11ty-cat-pages command you can execute during the Eleventy project build process since commands executed through npm now have access to the module.\nTo configure your project to execute it every time you build the site, update your Eleventy project’s package.json file to add or update the build command line this:\n\nThe rest of the steps in this article require real time execution of the module.\nConfiguration\nTo make this module as simple as possible to use, I built it so it uses a configuration file instead of command-line options to drive the process. Then, when you’re running it from the command-line, you don’t have to remember any parameters, all you have to do is execute 11ty-cat-pages and you’re done.\nYou don’t have to create the configuration file manually, the module does it for you the first time you execute the command. With that in mind, open a terminal window or command prompt and navigate to the Eleventy project folder. Once there, if you installed the module globally, simply execute the following command:\n\nIf you installed it locally, execute the following command instead:\n\nThe module will see that there isn’t a configuration file in the current folder and prompt you to create it.\n\nPress the y key to create the configuration file.\nConfiguration File\nThe generated configuration file is called 11ty-cat-pages.json and the module places it in the root of the Eleventy project.\nWhen the module creates the configuration file, it scans the project folder to see if it can pre-configure the file for you from the current project’s configura",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Algorithms Making Stuff Up",
  "date":"Tue May 30 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685491200,
  "url":"/posts/2023/algirithms-making-stuff-up/",
  "content":"\nThis post copied from my World Without Apps site.\n\nNot long after posting my previous article about ChatGPT, articles started popping up about a lawyer who used ChatGPT to write a brief for a court case and how it backfired on him because the generated brief had made up stuff in it.\nOf course it did.\nAs I mentioned in the previous post, ChatGPT is a next word prediction algorithm at its core. It’s job is to generate content based on its interpretation of the request made by the user. It has a huge body of work to pull from, so it ‘knows’ (notice the quotation marks) what a legal brief looks like and will dutifully write one for you.\nThe algorithm knows, from the content used to train the model, that legal briefs generally include one or more references to other relevant court cases. It knows this because, I expect, it’s seen a lot of legal briefs in its training materials, especially if it’s a model tuned to legal matters. It also knows this because in the body of content used to train the model there are examples of arguments (writers making a point or trying to convince someone of something) and those arguments list examples to help prove the argument.\nWhat’s the algorithm going to do?\nIts a next word prediction algorithm, not a research engine, so it ‘knows’ it needs examples and ‘knows’ it doesn’t have any in its ‘memory’. Of course it’s going to make them up.\nThe algorithm isn’t broken, it’s doing exactly what you want it to do.\nNow, if you wire the next word prediction algorithm with a research algorithm, then you can ensure that the references in the generated content are both real and relevant.\nThat’s the point I tried to make in Islands of AI Everywhere (/posts/2023/islands-of-ai-everywhere/). Stand-alone algorithms do one task and only one task (likely pretty well). While they appear intelligent, they’re only a highly trained software-based model (an algorithm) doing one thing as best it can. It's not until you wire hundreds, thousands, or millions of models together that you get AI useful for more complicated tasks (like writing legal briefs).\nNote: My most sincere apologies for all the quotes around so many words in this post. I generally hate it when people do that, especially for commonly used words, but I did it here to highlight that I mean the word, but a different view of what the word means.\nArticles\nHere are some links if you haven’t seen the story yet:\n\nHere’s What Happens When Your Lawyer Uses ChatGPT\nA lawyer used ChatGPT to prepare a court filing. It went horribly awry.\nLawyer apologizes for fake court citations from ChatGPT\n\nPhoto by Quino Al on Unsplash\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Artificial Intelligence"
  
  ]
  },

  {
  "title": "Migrating This Site from Joomla To Eleventy",
  "date":"Mon May 29 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685404800,
  "url":"/posts/2023/migrating-a-joomla-site-to-eleventy/",
  "content":"Earlier this year, I started playing with the Eleventy (https://11ty.dev/) static site generator. I ran this site on Joomla! (https://joomla.org/) for many years, and I love it, but they recently released a new update and I simply wasn’t up to doing the version migration. Migrating to a static site generator (SSG) would remove many of the security issues related to running Joomla sites on PHP.\nAfter playing with Eleventy for a while, I decided I would use it for this site going forward and started planning the migration. This site’s been around since 2009, so I had a lot of content to migrate, and I knew I needed migration tools to make this easier.\nLooking at the tasks I had to complete, the project looked something like this:\n\nBuild out the Eleventy version of this site (which includes picking out a cool template for the site).\nExport all of the Article and Category content from the MySQL database running the site.\nCopy all of the image files from the Joomla site to the Eleventy project.\nMigrate all of the exported data to Markdown format (what Eleventy uses for post content).\nClean up all of the posts.\nGo live with the new site.\nDelete the old site.\n\nBuilding the Eleventy Version of the Site\nBuilding out the site in Eleventy was easy, I’d just built a couple of sites using Raymond Camden’s A Guide to Building a Blog in Eleventy, so I had all the experience I needed with Eleventy. I created a list of features I wanted in the site and built each one out over several weeks.\nOne of the things I wanted for this site which was easy to do in Joomla but difficult to do in Eleventy is including category pages with pagination. Eleventy easily supports paginating article lists, and it’s also easy to make a categories page in Eleventy (/posts/2023/eleventy-site-categories-page), but Eleventy doesn’t support generating category pages with pagination. To get around this, I built a Node module called Eleventy Category Pages which I’ll write about here soon.\nFor the site template, I decided to use one of the Pixelarity templates. It was really easy to apply their templates to Eleventy sites, I’ll write about that here someday too. If you don’t want to pay for a Pixelarity subscription, you can find free versions of many of the Pixelarity templates at HTML5 Up.\nExporting Joomla Article and Category Content\nIn Joomla sites, Joomla links articles and categories using the category ID in the article record. So, in order to export all of the articles along with the category names, I had to export both the Joomla site’s categories and content tables.\nAt the time, I hosted the site at FatCow (https://fatcow.com/) and from the control panel I opened the MySQL database manager, selected my site’s database, then opened the MySQL Admin tool. From there, I selected the categories table as shown in the following figure.\n\nOnce I had the database table listed, I clicked the Export button at the top of the column list. MySQL Admin opens the export page offering me several options for the table export. In this case, all I needed was a Quick JSON export as shown in the following figure.\n\nThis created a categories.json file that looked like the following (with many of the categories removed from the example):\n\nI repeated the same steps for the content table (which contains all of the article content).\nDownloading Joomla Site Images\nDownloading the image files was easy too since Joomla sites keep them all in a single folder /joomla/images.  I opened an FTP client (I used FileZilla (https://filezilla-project.org/)), connected to the site, and downloaded all of the files in the site’s images folder to the Eleventy site’s src/images folder.\nIn both the Joomla and Eleventy versions of this site, I store all of the image files in a separate folder for each year’s content. I didn’t start that process until after I ran the site for a few years on the Joomla side, so I had to do some cleanup to move the downloaded image files into the correct year folder in the Eleventy site.\nMigrating Article Content to Markdown\nI knew that converting Joomla article and category data from JSON to markdown was going to be a problem. I expected there might be a tool out there to help me, but I couldn’t find anything, so I had to create my own. I created a Node Module called Joomla to Markdown, you can read all about it inJoomla Article Conversion to Markdown  /posts/2022/joomla-article-conversion-to-markdown/.\nTo export the article content, I opened a command prompt (I do most, but not all, of my development on Windows), navigated to the folder where I stored the exported Joomla database table data, and executed the following command:\n\nHere’s the details on the parameters to the command:\n\nI exported the database tables to a folder called data\ne4hy6 is the Joomla database prefix for my old site.\narticles is the name of target folder for the generated markdown files\n11ty.md is the Eleventy post template for the site\n--shortDate tells the command to prefix each article",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "What is ChatGPT?",
  "date":"Sun May 28 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685318400,
  "url":"/posts/2023/what-is-chatgpt/",
  "content":"\nThis post copied from my World Without Apps site.\n\nSeveral friends asked me lately what I think of ChatGPT and the other chat systems we hear a lot about lately on television and other media. The world is absolutely freaking out about this tech with doomsayers announcing the end of humanity and pundits digging up pictures of the Terminator for their posts.\nChatGPT isn’t really artificial intelligence (AI), it feels like it is, especially since the ‘conversations’ you have with it seem so… conversational. Its how intelligent feels that scares people today. At the end of the day, it’s just a next word predictor that uses a machine learning (ML) model to do the prediction, nothing more.\nNow, people working in the AI field are going to take offense to my statement about it not being AI, so let me explain.\nChatGPT isn’t intelligent; it’s the application of a very sophisticated machine learning model that predicts the next word in a sentence. That’s it! That’s all it does (as I understand it). It appears to be intelligent because of what it does, but it’s really not. It’s just the result of a very smart mathematical algorithm and it will NOT take over the world and destroy humanity. It can’t, because, in the immortal words of Terry Gilliam in Monty Python and the Holy Grail, “it’s only a model.”\nIt uses a probability calculation to predict what the next word will be in a sentence or paragraph, based on previous words in the sentence or paragraph and the data set used to train the model.\nIf you give it a small training set, say for example just the Gettysburg Address, ChatGPT has almost no chance of predicting anything. However, if you give it a very large data set to train from, say the contents of the Internet or a complete library of books, or even a subset of those, the probability that ChatGPT can guess the next word increases dramatically. With the whole internet at its back, any algorithm will seem intelligent.\nWhen you train a model with a very large (huge) data set and pass a sentence or paragraph repeatedly through the model (recursively more or less), adding each prediction then running it through again, you get a system that’s able to write sentences and paragraphs for you.\nThe power is in how the algorithm categories and stores analysis results, how much data the model has to work from, and how well it can find and use the data it has.\nSo, how does it work? I don’t know, I’m not an AI scientist. But I believe it’s something like this:\n\nThe user gives it some input like a question or a command\nIt uses Natural Language Processing of your question or command to build a semantic model of the input. At this point, ChatGPT knows what it thinks you said or asked for.\nIt applies its prediction model to the semantic model from your input and predicts the first word in a response.\nIt repeatedly feeds the semantic model and the generated output through the model again until the probability of it being able to predict the next word falls below a certain threshold.\n\nThat’s it, as far as I can tell - no way for that to take over the world and destroy humanity.\nDoes it understand previous queries and can it use that data to help improve the quality of responses for subsequent queries? Yes, absolutely. But it likely doesn’t keep anything but the current conversation in context. It could track the requests and responses from all queries worldwide and use that to improve prediction results, perhaps by users rating the results of every query, but the data set already consumes a tremendous amount of storage and the engine consumes a tremendous amount of computing power (compute) to process the queries.\nAndreessen Horowitz published an article that discusses the compute limitations of AI in Navigating the high Cost of AI Compute.\nAs I mentioned this briefly in Islands of AI Everywhere, stand-alone AI models are useful and interesting, but until you connect them together, and by this I mean millions of models, we’re not anywhere close to having true intelligence in AI.\nWith ChatGPT, there isn’t a huge bank of compute and storage keeping track of everything and making decisions. The only decision this algorithm makes is calculating the probability of a word being the right word for the next word in a sentence. Nothing more.\nWill we reach a time where we do have millions and more ML models feeding into each other to accomplish great things. Yeah, I think so. Will this happen in my lifetime? No, I doubt it. Will this produce sentience? Real intelligence?  It can, I think, but the compute and storage requirements for this are beyond comprehension today. So many technological advances are required coupled with everything in our world being connected. It is possible, even likely, but I don’t see it happening within 1,000 years or more (and I read a lot of Science Fiction).\nOK, what is going to happen next?\nWell, people are going to lose jobs as IBM has already announced Job cuts may intensify as IBM plans to use AI to replace 3",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Artificial Intelligence"
  
  ]
  },

  {
  "title": "Eleventy Displaying Posts from Another Site",
  "date":"Sun May 28 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685318400,
  "url":"/posts/2023/eleventy-displaying-posts-from-another-site/",
  "content":"As I explained in Relaunched A World Without Apps I just relaunched a sister site to this one. After I posted that article, I started thinking about pulling in the most recent posts from that site to this one's home page, just to cross link the sites. You can see the results on the home page, it looks something like this:\n\nSince the World Without Apps site has a JSON-based RSS feed, there wasn't a lot I had to do to make this work.\nFirst, I created a data file called wwa-posts.js in this site's scr/_data folder that looks like this:\n\nWhat this does is read the RSS feed, then returns the article items array as a global data set in Eleventy. With that in place, all I had to do was update the home page to use the list of articles:\n\nThat's it!\nThere are, however, several issues with this approach.\nFirst of all, the list will only update when I generate this site, not when I add a post to the A World Without Apps (WWA) site. I could, I guess, setup some sort of trigger so that whenever I add a post to the WWA site that triggers a build of this site. I may investigate the best way to do that and get back to you on that one.\nThe other issue is that I build and host this site using Netlify and the cloud build process didn't like my use of fetch in the JavaScript code I showed earlier. That's because the fetch() command isn't available in older versions of node.js that Netlify apparently uses by default. All I had to do was add an environment variable called NODE_VERSION to my site's configuration in Netlify and set the value to 18 and everything works great.\nNo JSON RSS Feed?\nThis all works because the WWA site has a JSON-based RSS feed in place, If you don't have one in your site, you'll have to do this a little differently.\nIn the source site, add a global data file to the site's src/_data folder, in my case I called it wwa-latest.liquid, and populate it with the following code:\n\nWhat this does is create a data file called wwa-latest.json in the site's root directory. The code limits the results to 5 posts, but you could easily change that by modifying the number in the limit: 5 statement in the code.\nWhen Eleventy builds the site, it creates a file that looks like this:\n\nWith that in place, all you have to do is read the file and use it in your site.\nThe first step is to switch to the target Eleventy project and add a global data file to the project, in this case, it's a slightly different version of the wwa-posts.js described in the beginning of this article.\n\nIn this case, the code reads the generated JSON file from the source site and returns it as an array of posts. With that array in hand, you use the exact same code to display the post list on your site:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Relaunched A World Without Apps",
  "date":"Sat May 27 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685232000,
  "url":"/posts/2023/relaunched-a-world-without-apps/",
  "content":"Back in 2016 I created a site called A World Without Apps where I published articles about voice interfaces and how they would replace many mobile apps. After letting the site languish for many years, I finally brought it back to life last week with a new look and new purpose.\n\nVoice-based systems are still a thing and much more prevalent too, my 2018 Audi and my wife's new VW both have voice response systems built in, so I was right back in 2016. What's happened lately, and why I brought the site back to life when I was about to kill it, is that chat-based AI systems are very big in the news right now and I have some things to say about them.\nYou can find the site at https://aworldwithoutapps.com and I hope to write there as frequently as I write here. Stay tuned.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Islands of AI Everywhere",
  "date":"Sat May 27 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685232000,
  "url":"/posts/2023/islands-of-ai-everywhere/",
  "content":"\nThis post copied from my World Without Apps site.\n\nI originally started this blog back in 2018 but never finished it.\nWhen I started this blog, I assumed voice interfaces were the key to everything I wanted to write about. It turns out that voice is key to the world without apps, but AI’s taking a bigger role in what happens when apps go away.\nIn 2018, I purchased a new Audi Q7. I splurged and purchased a model with the Vision Package which gives me a really cool 360 degree view of ground outside of the car when I’m backing up or parking in a parking spot. This feature isn’t AI in any way that I can tell, it’s just some fancy math to stitch together views from multiple cameras simultaneously.\nAnother Vision Package feature I love is the car’s ability to read speed limit signs. As I drive around, whenever the car ‘sees’ a speed limit sign, it reads it and displays the results on the dashboard. I can even set an alarm so it warns me by blinking the speed limit notification on the dash if I exceed the speed limit.\nThere’s a spot in my neighborhood where tree branches partially cover the speed limit sign and rather than guess about the speed limit, the car dutifully warns me, loudly and annoyingly, that it can’t read the sign.\nThe car isn’t smart, it doesn’t truly understand speed limit signs. It has a built-in Machine Learning (ML) model it uses to tell if it ‘sees’ a speed limit sign, and, when it sees one, it uses another ML model to transcribe the numbers on the sign into a number the car uses to craft the speed limit graphic on the dash determine if it needs to flash the speed limit exceeded warning there as well.\nFlash forward 5 years and the car still gives me the exact same warning every single time I pass by that particular speed limit sign in my neighborhood. This happens, and I’m only guessing here, at least 100 times a year, probably more.\nNow, I can probably solve this problem by driving over there one day with lopping shears in the back of my car and asking the homeowner if I can trim the branches, and perhaps I will someday. But fixing the visibility of the sign is not the issue here.\nSo we’re talking about Artificial Intelligence here, right? Where’s the intelligence?\nThe car has a GPS system as well, with an accurate set of maps and real time updates that show traffic levels on larger streets. Pretty cool stuff. With that in mind, I made the connection that since the car has GPS and the car knows it can’t read the street sign, it should be able to make the connection that every time it drives by the sign, it’s not going to be able to read the sign.\nGranted, someone could swing by and trim the branches, so it’s not guaranteed that it can’t read the sign every time, but work with me here.\nDon’t you think that over time, like after the 100th time the car warned me unnecessarily that it can’t read the sign, that the car would stop warning me? No, it doesn’t. It is a residential neighborhood, so the chances are that the speed limit will be 25 MPH no matter what anyway.\nThe car doesn’t make that connection because the two systems (GPS and Sign reader) aren’t interconnected. When the car sees it can’t read the street sign, it has no idea where it is at the time this happens. Well, that’s not true, the car knows where it is, but the speed limit sign reading model doesn’t. If these systems are so intelligent (the I in Artificial Intelligence) why didn’t Audi tie the two together so the system can learn about this and not give me the same lame warning for 5 years and more?\nNow, you may be thinking that the car doesn’t know this because it doesn’t know it’s me driving so it wants to make sure that anyone driving the car at this particular place knows that the sign can’t be read. Audi connects the key to the user settings, so as soon as I get in the car with my key, the car adjusts the settings to match. So, the car does know it’s me. On top of that, the car pairs with my phone every time I’m in the car, so when it’s my key and my phone, it doubly knows its me driving.\nYes, that’s a faulty argument, but my point is that the car has a lot of really interesting technology in it that are all islands, disconnected from each other. The speed limit sign reading capability is amazing, but the car only uses it to display either a solid or blinking speed limit image on the dashboard.\nI write this as the world is absolutely freaking out about Artificial Intelligence (AI) and the impact it has or will have on humanity. However, none of this is AI, it’s just a bunch of crafty ML that appears to be intelligent but isn’t. Until someone builds systems where hundreds, thousands or even millions of models work together to solve problems, we’re not even close to true intelligence.\nI’ll write more about this soon; I have some thoughts about ChatGPT and the like that I want to share with you, hopefully in the next few days.\n\nPhoto by Joshua Hoehne on Unsplash.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Artificial Intelligence"
  
  ]
  },

  {
  "title": "My Take On GitHub Projects",
  "date":"Fri May 26 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1685145600,
  "url":"/posts/2023/my-take-on-github-projects/",
  "content":"I worked at GitHub when they/we released GitHub projects and the capability was a nice addition to the source code repository. Most of the Azure DevOps Engineering team had just moved over to GitHub and GitHub Projects was, I think, supposed to be a first step toward adding Azure DevOps like capabilities to GitHub.\nWith GitHub Projects, you could:\n\nAdd multiple task tracking lists and boards to a repository\nDo all of your work related to the repository in the repository\n\nI recently did a big site migration from Joomla to Eleventy and I wanted a place to track all of the action items I made for myself as I worked through the migration. Remembering that GitHub Projects would likely give me what I needed, I opened a browser window, navigated to the repository, then clicked on the Projects tab.\n\nWhat I saw there confused me. Instead of the Create Project button I expected, instead I saw an option to Link a Project. Link a project? What does that mean?\n\nIt took me a few seconds to realize the button was also a drop-down, so I clicked the arrow and found the New Project button I expected. When I clicked the button, Projects gives me the opportunity to select the type of project I want as shown below.\n\nI created a Board since I wanted a Kanban board for my tasks and got to work.\nWhat I didn’t understand was that projects are no longer actually associated with the repository. GitHub now associates projects with the GitHub Organization or Account, not the repository as shown below. You can still access the project from the repository, but scoping the project to the account breaks everything I expect from Projects.\n\nI understand that GitHub is trying to replicate capabilities from Azure DevOps, for small time single developers this doesn’t make sense. It also makes it much more complicated to use Projects for what I want to use them for.\nLet me explain.\nWhen you create a new task in the board, it shows on the board like this:\n\nApparently the task is on the board, but for some bizarre reason the task is in Draft mode. Draft has no context here, I created it and added it to the board column I wanted, there is no draft context here.\nI had to start searching around on the Internet to find the answer to this one. In Projects, Draft status means that it’s not connected to an issue in a repository in the account or organization. Not only can I not make a task and have it stick, I have to manually create an issue from the task before the task will move out of draft mode. This makes absolutely no sense to me, but wait, it gets worse.\nTo convert the task to an issue, you must hover over the task and click the little three-button thingie that appears. Once you do that you see an option to convert the task to an issue.\n\nOnce you select that option, you’re prompted to select the repository you want to link the task to.\n\nOK, that makes sense when you look at this from an organizational standpoint and GitHub thankfully puts the current repository (the repository I created the project in) as the first option in the list. What doesn’t make sense is that I have to do this at all.\nWhat GitHub should do is automatically create the associated issue in the current repository, then give users the option to move it somewhere else.\nOne I figured this out, I manually created issues for all these tasks even though the project should have done this for me automatically. Next, I worked through my workflow, moving tasks from ideas to todo, in-progress, all the way to done.\nWhat happened to my issues through all of this? Nothing. Not a damn thing.\nPutting tasks in as drafts makes no sense. Letting me assign them to issues makes some sense, but, again, I want this to be automatic. Updating the issues as I work on them is MVP in my mind.\nSo I now have all of these issues in my repository and a board to manage them, but the board does nothing to manage them.\nNow, I know (or at least I assume) I can setup automation to enable the workflow process I’m using but honestly I expected this to happen automatically. You gave me the board template, so you know how people expect it to work. Why force another manual task on me?\nI don’t get it. You can tell that other GitHub users don't get it as well: why is everything a draft?\nKnowing that I’m a single developer working in this repository, GitHub should deliver the board experience that fits with a single user. When I’m in an organization, all this other stuff could make sense, especially when the board pulls issues from multiple repositories.\nWhat this means for me is that I dropped using GitHub Project for task management and instead activated my Trello account.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Developer Tools"
  
  ]
  },

  {
  "title": "Generating Post Batches in Eleventy",
  "date":"Mon May 15 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1684195200,
  "url":"/posts/2023/generating-post-batches-in-eleventy/",
  "content":"As I built the Eleventy Post Stats plugin, I realized I needed a bunch of posts (hundreds) distributed over multiple years to test the plugin as I developed it. Also, since I worked on at least two different development systems (Windows and macOS) and I didn't want to store the dummy posts in GitHub, I had to create posts on each system to do my testing.\nNow I could copy over the posts from this site or make a few posts and copy them multiple times, I decided I didn't want to do anything like that. I knew that I'd build other plugins or Eleventy sites and hopefully present at conferences about Eleventy, so I decided to build a post generator that would accept as an input the number of posts and then generate the posts for me.\nI didn't want to have to create a configuration file and post template like I did for my Eleventy New Post package, so everything had to work from a simple command-line interface.\nBecause of the way my Post Stats plugin works, I also needed the posts spread across time to affect the average days between posts calculation the plugin does, so I needed a way to [optionally] give the package a start year for posts and a way to spread posts across a time period.\nI use a post tag on my posts to tell Eleventy how to display them, so I needed a way to pass that tags value.\nFinally, since Eleventy sites can have different folder structures, I needed to be able to tell the package where to put the generated post files.\nThe result of this is my Eleventy Generate Posts package available on npm\nInstall the package using:\n\nThis adds a 11ty-gp command to the system.\nWith that in place, you can generate batches of posts using the following command:\n\nSupported command-line options are:\n\nnumPosts (required) An integer value representing the number of posts generated.\ntargetFolder (required) Relative path pointing to the Eleventy project's posts folder; use . for the current folder.\ntag (required) The post tag applied to the generated posts\nstartYear (optional) The starting year used for post date in the generated posts.\n\nSo, how does it work?  When you execute the following command:\n\nthe command creates ten posts in the Eleventy project's posts folder with the post's front matter tags assigned the property post. The date for the first post is the current date, then the command works backwards by random days decrementing the date for future posts.\nIf you need posts in your site for a particular year, just add the year to the end of the command line like so:\n\nIn this case, the command takes the current date and replaces the year with the provided year and uses that date for the starting point for the generated posts.\nFor content, the command uses the Free Random Word Generator API to generate post titles using between 3 and 7 random words for each post. Here's some sample posts titles from a run I just did:\n\nBarista Comfy Evasive Resent Refold Murky\nDrinkable Clavicle Mop Subprime\nEloquent Anaconda Shorts Trousers Stifle Hertz Outplayed\nEnroll Canola Chewy Librarian\nHence Stability Astound Vigorous Stimulus Unheated\n\nThe command also uses the infamous Bacon Ipsum Generator to generate a random number of meat inspired paragraphs.\nYou can generate between 1 and 100 posts per command execution; I added the limit because I figured I'd never need more than 100 and I didn't want to bump up against any API calls per minute limits from these free APIs.\nHere's an example of the command in action:\n\nPlease let me know what you think of it; I'm unsure whether tags is the most flexible way to identify posts.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "GitHub JavaScript Module Used By Panel",
  "date":"Sun May 14 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1684108800,
  "url":"/posts/2023/github-javascript-module-used-by-panel/",
  "content":"This isn't going to be an earth shattering post, but I was looking at the GitHub page for the Eleventy Plugin Post Stats project I wrote about in an earlier post. I noticed that there was a section on the page I never noticed before, Used by.\nApparently when you publish a JavaScript module to GitHub then use it in another project published to GitHub GitHub shows you all the projects that use the module on the module's page. That's pretty cool and, I assume, time saving. Its cool to see GitHub add quick little time-saving features to the portal.\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Web Development"
  
  ]
  },

  {
  "title": "Automating Eleventy Post Creation",
  "date":"Wed May 10 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1683763200,
  "url":"/posts/2023/automating-eleventy-post-creation/",
  "content":"I really prefer writing blog posts here using Markdown instead of the CMS-based tooling of my old site. Its faster, easier to highlight code segments, and I can use whatever tooling I want.\nNot having a CMS underneath the site, it’s not just a click of a button to create a new post. I basically have to copy an existing post, then update the post’s front matter to reflect the current date, title, and categories. I could keep an empty post lying around in the site’s root folder and copy that file to eliminate some of the steps (replacing front matter content and post content) but I’m still copying and pasting.\nSince I plan to do a lot of writing here this year and beyond, I started looking for a way to automate the process. I wanted a process where the only typing I had to do was entering new information in the post, not replacing existing stuff.\nSince Eleventy is node-based and I love working in JavaScript and writing node-based command-line utilities, I (surprise!) decided to build a node package/command for this.\nThe package is called Eleventy New Post and you can find the source on Github and npm.\nTo install the command, open a terminal window or command prompt and execute the following command:\n\nWhen you're done, you have a new command called 11ty-np you can use to quickly and easily add a new post to your Eleventy site.\nAfter you install it, execute the command to initialize the environment to use the command.\n\nTo avoid command line options I'd never remember the order of, the command creates a configuration file that contains all the required settings for the command:\n\nWhen its done, you'll have a new file in your Eleventy project's root called 11ty-np.json:\n\nHopefully the configuration options are self-explanatory, but I'll help you out anyway.\nUse the postsFolder to define the relative path to the folder in your Eleventy project where you store your post files. The command checks what I think are the standard places for posts, so you should see this configuration option already populated for you.\nThe command uses a template file as the template for every post file it creates. Take one of of the posts from  your site, remove the title, date, and categories properties from the file's front matter plus the post content from the file and save it to the project root folder. Next, populate the templateFile configuration value with the file name for the template.\nSome Eleventy project stores posts in a separate folder per year (this site does). When you set this value to true, the command places the new post in a sub-folder of the postsFolder for the current year. When false, the command puts all posts in the postsFolder folder.\nThe command supports a command-line flag that enables population of the new post body with dummy content generated using the popular Bacon Ipsum generator. The paragraphCount configuration option defines the number of content paragraphs generated with this option enabled.\nThis site's template file is called, unsurprisingly, 11ty-np.md and it looks like this:\n\nPut as much or as little content in the file as you need to create posts that work for your site's configuration.\nWith all that stuff in place, execute the 11ty-np command with no command line options. The first thing that happens is that you're prompted to enter the title for the post:\n\nNext, the command reads all the posts for your site and builds a list of all the categories in use in the site. With that list ready, it prompts you to select one category to use for this post:\n\nIt only supports selection of a single category, but you can add more categories when you edit the post to add your content. If you don't want to assign a category to the post, select the 'Uncategorized' option in the list and the command will leave Category blank in the new post.\nAt this point, you're done - the command generates the post, writes it to disk (in the posts folder or a separate subdirectory for the current year) and you're all set.\n\nIf you want to see more stuff in the terminal as the command executes, add the -d flag to the command-line.\nTo generate bacon ipsum text for the generated post, add the -p flag to the command-line.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy"
  
  ]
  },

  {
  "title": "Eleventy Site Statistics",
  "date":"Tue May 09 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1683676800,
  "url":"/posts/2023/eleventy-site-statistics/",
  "content":"As I worked to migrate this site to Eleventy, one of the final touches I wanted to add was a statistics page that showed 'stuff' about the site. The page started simple at first, but then I started thinking about what I could do with 14 years of post data.\nI knew I could add a collection to my site and use that to build a data set showing the number of posts per year as well as the average number of days between posts. At that point, I realized I could make an Eleventy plugin out of it so others could use it as well and this would give me an opportunity to learn how to make Eleventy plugins.\nI published the plugin yesterday as Eleventy-Plugin-Post-Stats and added the complete Stats page to the site.\nYou can find the implementation of a page that uses all of the properties of the stats object in this repository's index.liquid file. Here's the source code for the page:\n\nI'm in the process of tightening up the table, but here's what the page looks like today:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Gadget Man",
  "date":"Wed May 03 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1683158400,
  "url":"/posts/2023/gadget-man/",
  "content":"Last summer we were on vacation with my wife’s family and when my wife started describing me as a gadget man, somehow someone started singing Rocket Man (by Elton John) using Gadget Man instead for the main theme for the song. We had a lot of fun singing the verses and belting out the chorus.\nI turned 60 last year and for my birthday my wife gathered my closest local friends together for a surprise party. There’s a lot more to tell about that particular event, but for now here’s what I wanted to write about now.\nIn preparation for the party, she and a couple of neighbors wrote an actual Gadget Man song and serenaded me at the party. It was amazing fun and I have a video of it that I won’t share here, all you get are the lyrics my wife, sister in law, and friends put together for the event.\n\nHe works for Or-a-cle – that’s his day job.\nHe’s published books about software.\nAnd he loves the wor…..ld of  tech, my friend.\nHe loves his kids -- he loves his wife,\nAnd Dexter – that’s his pup.\nIt’s such a fi….ne -- life for John.\nBut there’s something that he loves to find online\nThat feeds a joy for him deep inside.\nWe know the man who likes to share that joy,\nOh yeah, yeah, yeah,\nJohn’s the Gadget M..a..n\nGadget Man – he knows where to find the coolest toys.\nAnd he always on the hunt for some new tool\nTo keep or give away to those who find\nThey need a m.a.n who will do the search\nOh yeah, yeah, yeah…..\nHe’s the Gadget Man – Gadget Man - he knows where to find the coolest toys.\nSo if you have a flat -- or lose your lights\nJohn’s got -- the perfect fix\nCause he’s the one to call  --  for emergencies.\nHe searches for -- the perfect tool\nTo solve a problem -- just for you\nGadget m..a…n, Gadget man\nBut there’s something that he loves to find online\nThat feeds a joy for him deep inside.\nWe know the man who likes to share those toys,\nOh yeah, yeah, yeah,\nJohn’s the Gadget Man\nGadget Man – he knows where to find the coolest toys.\nGets his kicks by finding tools that fix\nHelping out gives him lots of joy\nHe knows where to find the coolest toys.\n\nIt’s an amazing song and it was an amazing night. I’m so happy to have a wife and friends that know you well enough to make fun of you in a song.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Meta Description and Keywords in Eleventy",
  "date":"Sun Apr 30 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1682899200,
  "url":"/posts/2023/meta-keywords-in-eleventy/",
  "content":"As I built out this site, I realized that since I had a description for many of the posts and an array of one to many categories for each, I could populate each page's meta description and keywords properties.\nDescription was easy, I added a description property to my post template and populated it for my newer posts. With that in place, the code simply checks to see if the description property is populated and, if so, adds it to the page:\n\nFor keywords, building the comma separated list of categories is a little ugly in Liquid (doable, but not elegant):\n\nInstead, I decided to add a GetKeywords shortcode in the project's eleventy.config.js like this:\n\nNow, with access to the keywords array of categories, adding it to each page's header was as easy as:\n\nThe difference is in code readability and output. In the first example, Eleventy generates the following HTML:\n\nFor the second, Eleventy generates the following:\n\nWhich, as I hope you see, is much cleaner; with the solution I picked I got cleaner code and output - always a goal for me.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Eleventy Extra Spaces in Category List",
  "date":"Sat Apr 29 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1682812800,
  "url":"/posts/2023/eleventy-extra-spaces-in-category-list/",
  "content":"As I built out this site, I added a list of category links to the post page as well as any post listings on the site. I grabbed the code from to do this from A Complete Guide to Building a Blog with Eleventy and it looks like this:\n\nIn this site, I display a little more information on the line as shown below:\n\nWhat I noticed is that on my site, Eleventy put an extra space before the comma for every category. I got a category list, but it didn't format correctly, there was a space before the comma and another one after the comma. Not exactly what I wanted.\nLooking at the code, notice how the lines break a little differently than in Ray's example, that's because, I think, I'm using the vscode-liquid plugin for Visual Studio Code and it restructures liquid code and removed the space after the comma. I love the automatic restructuring, but I think that's what broke this for me.\nI searched around and couldn't find a solution for this online. I eventually got help on the 11ty Discord. Apparently Liquid helpfully adds a space for you (even though you may not want it to); the solution is to use a dash (-) in the start of the Liquid template to tell Liquid not to add the extra space.\n\nThe complete code block looks like this:\n\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Eleventy Enhanced Pagination Navigation Buttons",
  "date":"Sat Apr 22 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1682208000,
  "url":"/posts/2023/eleventy-enhanced-pagination-navigation-buttons/",
  "content":"I added navigation buttons to this site on the Articles and Categories pages. I started with the standard Previous/Next buttons but quickly realized that I also wanted First and Last buttons, but only under certain conditions.\nFor example:\n\nI didn't want the Previous and First buttons displayed when the site visitor was on the first page, that's just silly, because the button wouldn't do anything.\nI also didn't want the First button displayed on the second pagination page because the Previous button already delivers the same functionality.\nFor the same reasons, I wanted tighter control over the buttons at the end of the list as well, so not displaying the Last and Next buttons on the last page nor the Last button on the penultimate page.\n\nHere's the Liquid block I came up with to implement this:\n\nThe only real tricky part was determining the delta from the last page to use for comparison purposes. Liquid wouldn't let me do the math I needed in the comparison, so I had to pull the calculation out into a variable assignment:\n\nThe first line inside the conditional delivers the traditional 'Page # of #' heading above the buttons.\n\nThe rest is, I hope, self explanatory.\nSince I used this block in two places in my site, I moved the code to an include and referenced it from both pages that need it.\nI hope this helps you with your Eleventy projects.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Site Migration Completed",
  "date":"Thu Apr 20 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1682035200,
  "url":"/posts/2023/site-migration-completed/",
  "content":"For fourteen years now, this site ran on the Joomla! Content Management System hosted at FatCow. I migrated the site several times between multiple versions of Joomla! 1x through Joomla! 3x and it was time to migrate to Joomla 4.\nSince I started working on this site, I built multiple sites using a variety of other content management systems (CMS) such as WordPress, Drupal, and Concrete 5. I also dabbled with several static site generators, most prominently Jekyll and recently discovered Eleventy.\nAt this point, I had to make a decision to stick with Joomla! or migrate the site to Eleventy.\nOver the years, FatCow became markedly less reliable as a hosting platform with decreased performance, slow technology upgrades, and basic incompatibility with modern CMS. They were acquired at least once, and support deteriorated over time. Due to this I knew I didn't want to keep the site at FatCow.\nI also knew that the Joomla! 3.x upgrade to Joomla! 4.x was a real migration. It looked on paper like it would work reasonably well, but with the site being so old, migrated so many times, and with the decreased performance of and at FatCow, it would be doubly hard to migrate it between Joomla! versions as well as hosting providers.\nI'd looked at Eleventy a bit, but never got around to building a site on it. I finally got some time to play with it and built a site for my daughter at The Cosplayer's Workshop and I learned that I love it.\nI'm a software developer in my core, and I love writing code and figuring out cool and interesting things using code, so the thought of building the exact site I wanted using Eleventy was exciting. I set about creating a new Eleventy project, assembling all of the parts, and building out the site.\nIf you're reading this post, you're on the new site already. It took me a few weeks to complete the migration, and I built and published a few tools to help others with similar migrations. I'll publish articles about the migration and all of the tools as soon as I can. In the mean time, you're looking at the new site, here's what it used to look like:\n\nThis is quite an improved Interface, and should be a lot faster than the old site. I'll also be able to build out some new data-driven areas of the site for my books, articles, GitHub projects, and so on. Stay tuned for more posts about all the things I'm doing here.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Automating Algolia Index Updates",
  "date":"Sat Mar 18 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1679184000,
  "url":"/posts/2023/automating-algolia-index-updates/",
  "content":"I recently started working with the static site generator Eleventy; since then I built a new site using it, and migrated an existing site from Jekyll to Eleventy. As part of that process, I followed Raymond Camden's Adding Algolia Search to Eleventy and Netlify to offer search for the site.\nIn the article, Ray suggests hosting an Eleventy site on Netlify and using Netlify Functions update merge Algolia Index updates with the cloud. However, he expressed concerns about the time limit on Netlify Functions executions and the potential impact on larger sites. When I get to migrating this site, I don't have nearly the number of posts that Ray has, but I don't want to monitor the process to ensure the index update works.\nI'm likely going to build and test any changes I make on the site locally, so I built a node-based command-line utility I'll use to update my index. I took the example code from Ray's article and packaged it in a simple node packageI can add as a development dependency in my sites and automate the index update. The package is called Algolia Index Update, and you can find it on GitHub and npmjs.org.\nI just realized that I made a mistake in the package. To enable it to work locally as well as a build task in a cloud hosting site, I store the index name and secret Algolia API keys in environment variables. As soon as I have more than one Eleventy site using Algolia, that's going to break. I'll have to update to store the index name locally with the site, perhaps in the package.json file or pass the index name on the command line. Stay tuned on that one.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Eleventy Site Categories Page",
  "date":"Fri Mar 17 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1679097600,
  "url":"/posts/2023/eleventy-site-categories-page/",
  "content":"I used Raymond Camden's excellent A Complete Guide to Building a Blog with Eleventy (https://cfjedimaster.github.io/eleventy-blog-guide/guide.html) to learn how to use Eleventy (https://11ty.dev/). In that tutorial, Ray generates a separate categories page for each category, then links to the category page from the list of categories on each Post. That's an excellent feature, and I wanted that for my site, but I also want to present users with a stand-alone list of categories they can browse directly from the site's home page.\nTo do that with Ray's tutorial, I made a few changes. FIrst of all, I renamed the categories.liquid page to category.liquid then updated all references to it in the site (basically updating the post.liquid include).\nNext, I added a new categories.liquid page with the following Liquid code:\n\nOnce I added the Categories page to my site's menu, I was all set.\nThis is something I tried to do in a Jekyll site and never figured it out. With Eleventy it took me just a few minutes to set up.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Displaying Build Details in an Eleventy Site",
  "date":"Tue Mar 14 2023 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1678838400,
  "url":"/posts/2023/displaying-build-details-in-an-eleventy-site/",
  "content":"I recently started using Eleventy, a node-based static site generator and quickly put up a new site using it. With that under my belt, I migrated my Random Errors site from Jekyll to Eleventy pretty quickly. My long term plan is to migrate this site from Joomla to Eleventy as soon as I figure out a couple of extra features I need for this site's migration.\nIn the meantime, I will share my learnings along the way.\nAs I played around with the Random Errors site during the migration, I realized I wanted to be able to show the site's build date in the footer. Not because it was necessary to do so, but because I wanted to figure out how to do it in Eleventy.\nSince Eleventy is a static site generator, you can simply write the current date/time to the appropriate pages at generation time. Using Liquid, this is pretty easy:\n\nIf you have a large site, and it takes a long time to generate all the pages (more than a minute for example), I imagine you could see different times on different pages because of that processing, but that's something I didn't validate. I'm not sure if Eleventy parses templates once then uses a cached version during site generation or whether it parses it every time.\nI know that over time I'm going to add new features to the site, updates to the site's structure or capabilities rather than just publishing new articles, how can I display platform build information on the site?\nSince Eleventy is node-based, Eleventy projects have a package.json file that contains a build number in its version property. Here's the file contents from the Random Errors site:\n\nThat means I can use the version property along with the date/time that the version number was updated and display that data as my platform version and timestamp in the site. Let me show you how I did that.\nIn Eleventy projects, you can create data files in the project's _data folder and the site generator will automatically load the file's contents as a data set named with the data file's root file name (the part before the dot and file extension). So, as described in Global Data Files in the Eleventy documentation, if I create a JSON file in the _data folder with the package version and a date/time stamp, I can automatically access the data as Eleventy generates the static site files.\nI could just add a buildDate property to the site's package.json file and copy that file into the _data folder every time I generate a new version of the site's files. But I'm an automation guy, so I knew there had to be a better way.\nThe npm CLI exposes the [npm version](https://docs.npmjs.com/cli/v9/commands/npm-version){target=&quot;_blank&quot;} command that allows you to automatically update the version number in the package.json file. I can use that to increment the version property automatically during the build process.\nUpdate the scripts section of the package.json file and add a build section as shown below:\n\nWhen you're ready to do a new build of the site, open a terminal window or command prompt and execute the following command:\n\nAt this point, npm updates the version number in the package.json file (represented by the v0.0.4 shown in the output below. Next, the Eleventy site generator kicks in and generates the site's files as shown below (with most of the site's pages omitted).\n\nThat gets me an updated version number for my site, but doesn't help me put the data I need (the version number plus the build timestamp) into the site's _data folder.\nSince Eleventy is a npm-based static site generator and I like to write node-based command-line utilities, I realized I could build a little utility that took care of building the data file I needed, even copying the file to the _data folder in my site.\nThe utility is called Generate Build Info and you can find it on npm at https://npmjs.com/package/generate-build-info. What it does is read the version property of the current project's package.json file, then writes a buildinfo.json file to a folder you specify containing the build details for the project:\n\nThe buildVersion property is the version property from the package.json file, and the buildDate properties are the current time in two different formats you can use in your Eleventy site: Milliseconds since Epoch or a date/time string.\nTo use it, open a terminal window or command prompt in your eleventy project's root folder and execute the following command:\n\nThis adds the utility to the project's development dependencies (you don't need it at runtime); you'll use gen-build-info to generate the data file. With that in place, update the package.json build command like this:\n\nIn this example, my _data folder is in the project's src folder, so I want the utility to put the data file there. When you execute the npm run build command again, it updates the project's npm patch version, generates the buildinfo.json file and copies it to the src/_data folder, then executes an Eleventy site generation. Easy peasy.\nIn your Eleventy project, Eleventy automatically ",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Eleventy",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Synchronizing CircuitPython Files",
  "date":"Sun Feb 19 2023 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1676851200,
  "url":"/posts/2023/synchronizing-circuitpython-files/",
  "content":"I love working with a variety of microcontroller devices and a lot of my projects use LEDs, so I was pleasantly surprised when the folks at Adafruit added the FeatherS2 Neo (https://adafruit.com/product/5629) board to their catalog. It has an ESP32 processor and a 5x5 grid of little NeoPixels onboard, so it is perfect for some of my projects.\nThe board comes configured to use CircuitPython (https://circuitpython.org/) by default, although you can also program it in C in the Arduino IDE. I haven't done much CircuitPython work in the past, so I thought I'd learn more about it as I worked with the board. I'll publish some of my projects for it as I progress, but this article is about the CircuitPython development workflow and a tool I created to tweak that workflow to suit my particular needs.\nWhen you connect a CircuitPython (CP) device to a computer using a USB cable, the CP device manifests itself as a connected drive. On my Windows development system, due to all of the other drives I have connected to it, the CP device appears as drive H. On the macOS system, where I'm writing this article, it appears as /Volumes/CIRCUITPY.\nDeveloper tooling reads and writes directly to/from the 'drive' to deploy executable code to the device (in this case, written in the CP variant of Python). There are even Python editing tools like Mu (https://codewith.mu/) or extensions for popular editors like Visual Studio Code (https://marketplace.visualstudio.com/items?itemName=joedevivo.vscode-circuitpython) that understands how to interact with connected CP devices. The developer connects the device and opens an editor and codes away. The tooling I mentioned also provides additional capabilities that assists with monitoring and debugging an application as it runs on the CP device.\nThis approach works great for new developers and classroom environments. All the learner has to do is plugin the device, open an editor, and away they go. As the learner moves from classroom to home, all of the code they need is already on the device, they can edit it anywhere they want then unplug the device and take it with them.\nI'm used to a different development workflow.\nIn modern development workflows, developers work in a local code project (in a project folder on a local hard drive) or in the cloud (accessed using a browser-based editor for example). In that workflow, changes to the project's code are tracked and managed through a version control system like Git and synchronized between development systems through a cloud repository like GitHub. When working with a microcontroller or single board computer, I'm used to coding in my local project folder and deploying code to the device when it's ready to run on the device. As I complete features, I commit them to the version control system and push them to the cloud for sharing.\nWhat I want to do is use this type of Git-based workflow with the CP device.\nI could create a git repository on the connected CP Device, code away on the device and commit my changes to the repository on the device then synchronize that device-side repository to the cloud. That would work, but this is still very device-focused; the primary storage location for my code is the device, not my local development system.\nAnother option is to code locally, then copy the files to the CP device. This could be a simple shell/command script and would work, but the CP-aware editors expect to read/write to/from the device, so that would eliminate those types of tools from my tool belt.\nWhat I decided to do instead is leave the development workflow like it is, use the CP-aware tools that expect to interact directly with the connected device and copy the code to my local project folder. I could create a local folder for the project code, set up a Git repository in the folder, then copy the code files from the CP device periodically as I work on the project. I could implement this as a simple script, all I'd have to do is make sure I ran it whenever I had new code to copy.\nRather than write a script or copy a script into every project, I decided to create a tool I could use in any project and share with others to use with their projects as well.\nThe tool I created is a node-based command-line module called CircuitPython Sync (cpsync), you can access the code on GitHub (https://github.com/johnwargo/circuitpython-sync) and install it on your development systems using Node Package Manager (npm) (https://npmjs.com/package/cpsync).\nI wrote it in NodeJS because I have a lot of experience using node in many of my other projects and it's a standard part of many modern software development workflows. I expect I'll someday rewrite it as a standalone executable using Rust.\nTo use the tool, you open a terminal window (macOS or Linux) or command prompt (Windows) and execute the cpsync command (passing in the correct arguments, of course - all describe on the Github or NPM pages) and it will setup a file change listener on the CP device. Then, with th",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Joomla Article Conversion to Markdown",
  "date":"Tue Nov 22 2022 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1669161600,
  "url":"/posts/2022/joomla-article-conversion-to-markdown/",
  "content":"I've been running johnwargo.com on Joomla since the late 2000's, upgrading as needed from Joomla 1, Joomla 2, and Joomla 3. The Joomla team recently released Joomla 4 and Joomla 3 will reach end of life next year. As I started working through the Joomla 3 to Joomla 4 upgrade process, I realized that my site was broken and I couldn't get any help from my ISP.\nWith that in mind, I started thinking about how I could easily migrate all of my existing article content to another CMS. I'm experienced (a bit) with Jekyll and have always wanted to learn more about Eleventy (11ty). I definitely didn't want to do all of the article conversion myself, so I started thinking about how to build a tool to do all of it for me. \nI knew Jekyll uses markdown files and Eleventy supports them as well, so I decided to convert my content to markdown thinking that with the right conversion template, I could migrate my site's articles to almost any CMS. \nI've published several node CLI modules in the past (for managing Jekyll assets and to simplify the Moddable CLI), so I decided I'd build this one in Node as well. I recently learned about the Open CLI Framework (https://oclif.io/) and wanted a chance to learn that framework.\nThe result of all of this is that I recently published a node module called Joomla to Markdown (joomla-to-markdown) available at https://npmjs.com/package/joomla-to-markdown. \nTo use this module, export your Joomla site's Categories and Content tables to JSON files using MySQL Admin (or similar tool). Then, with a couple of simple terminal commands you can parse the article and category content and output a separate markdown file for each article in the Joomla site. \nI built the module so it uses a user-defined template file to define the format of the markdown file and allows you to add any field from the Joomla site's Content table to the markdown file. Its all pretty simple to use and available today.\nI wrote the module to be completely command-line driven, where the user provides the parameters the module needs to operate on the command line, but it got tedious typing them in all the time. I'm currently working on an enhancement to the module which uses a local configuration file to run the process (as an alternative workflow) so you can tweak the template and quickly rerun the export without typing all sorts of command line options. I'll have that version of the module published after the US Thanksgiving holiday (2022).\nI hopped back into my Joomla site and after making some tweaks was able to get it back up and running - hence my ability to publish this article. This probably won't last long, I'm going to redeploy this site on Jekyll first then Eleventy once I've got everything I want to do figured out. Stay tuned, I know I'll write about the experience once I do it.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems",
  
    "Static Site Generators"
  
  ]
  },

  {
  "title": "Site Upgrade Coming",
  "date":"Thu Nov 10 2022 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1668124800,
  "url":"/posts/2022/site-upgrade-coming/",
  "content":"This site runs on Joomla, since, I think, the Joomla 1.x days. The Joomla team recently released Joomla 4 and they're getting ready to shut down support for Joomla 3. In preparation for this, I removed the site map menu and upgraded the SEO engine.\nI haven't used attachments in this site in a long time, so I will soon delete the attachments plugin and update all articles that had attachments (10 articles). I'll put a notice on the top of each affected page and, if the attachment is still relevant, store it somewhere else and provide a link to the file's new location.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Apache Cordova API Cookbook Site Retired",
  "date":"Tue Feb 08 2022 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1644364800,
  "url":"/posts/2022/apache-cordova-api-cookbook-site-retired/",
  "content":"\nI shutdown the web site for my Apache Cordova API Cookbook book today. The book came out in 2014, and Apache Cordova has evolved a lot since then. Many of the source code examples in the book may still be valuable to new Cordova developers, but I've not validated any of the code against current Cordova versions in many years.\nYou can still buy the book on Amazon and other places, but there's no longer the need for a promotional website for the publication. Don't worry, the code from the book is still up on GitHub.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Apache Cordova 4 Programming Site Retired",
  "date":"Tue Feb 08 2022 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1644364800,
  "url":"/posts/2022/apache-cordova-4-programming-site-retired/",
  "content":"\nI shutdown the web site for my Apache Cordova 4 Programming book today. The book published way back in 2015, and Apache Cordova has evolved a lot since then.\nYou can still buy the book on Amazon and other places, but there's no longer the need for a promotional website for the publication. Don't worry, the code from the book is still up on GitHub.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Accurately Calculating Progress in Goodreads",
  "date":"Sat Jan 08 2022 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1641686400,
  "url":"/posts/2022/accurately-calculating-progress-in-goodreads/",
  "content":"I love writing utility applications; for many, many years I worked in the Enterprise space doing technology transitions and one of my favorite things was to write little pieces of code to solve problems big and small. For this blog post, the problem I’m dealing with is for a free app from Amazon called Goodreads.\nFor years, Amazon had two social apps that allowed people to track the books they read: Shelfari and Goodreads. They eventually shut down Shelfari and merged everyone’s data into Goodreads. That saddened me because Shelfari was a much better app than Goodreads and delivered a more consistent experience across platforms. Goodreads delivers a different user experience (UX) on different platforms (browser, native mobile apps) and I really kinda hate it. I’ve gotten used to the android app user experience, but when I sometimes have to use a browser instead, I’m completely lost in completing some tasks.\nI use Goodreads because it lets me track how many books I read in a year (last year I read 68 books out of my goal of reading 50). It also allows me to see the books family and friends are reading, so it gives me great suggestions on what to pick up next. When I’m reading a book, Goodreads allows me to publish an update showing friends what I’m reading and how far into the book I am. The problem is that for many books, the information Goodreads uses to calculate percentage completion based on page number is inaccurate, making the progress value inaccurate as well.\nThis happens because for some books, the pagecount data Goodreads has for some books is incorrect. This happens either because their source provides incorrect information or because there are multiple formats for a particular book which gives them different page counts. In some cases, I’ve seen places in Goodreads where I could pick a different publication for a particular book I’m reading, but I’ve not been able to find that particular area of the product in a while so I just give up.\nWhy Goodreads would have an incorrect page count makes no sense to me since Amazon knows everything there is to know about books sold through Amazon (where I usually get mine). Why Goodreads would hide the ability to let me pick the format/edition of the book I’m trying to read is beyond me.\nThe pagecount issue also rears its ugly head because of a more mundane problem. Many business, technical, historical, etc. books have indices and notes pages tacked on at the end which make any progress calculation inaccurate.\nFor example, I just finished reading Undaunted Courage by Stephen Ambrose and according to Amazon and Goodreads, the book has 521 pages. In reality, the readable part of the book, the stuff that most of us would consider the meat of the book, is 484 pages.\nSo, if I’m on page 100 of the book and I update Goodreads with that number, it calculates that I completed 19% of the book. In reality though I’ve completed 20% of the book. That’s not a huge difference, but it matters; some books have much larger indices so it matters more for them.\nAfter years of posting inaccurate progress percentages I decided to do something about it. I sat down and cranked out a quick application that takes the page number, actual page count, and total page count then spits out an adjusted value scaled to the total page count. You can find the application here: https://goodreads-page-adjuster.netlify.app/ and the source code for the project here: https://github.com/johnwargo/goodreads-page-adjuster.\n\nWhen you access the app, you’re prompted for the values shown in the image below. Enter the appropriate values for the book you’re reading and you’re all set. I added a copy button because I frequently do this on a mobile phone and I didn’t want to have to mess around with selecting and copying the resulting value.\nAs you can see, I’ve setup the parameters for Undaunted Courage. When I’m on actual page 100, for the Goodreads total page count that would be 107 pages. When I copy the value from here and paste it into Goodreads, Goodreads will show an actual progress percentage based on the total number of pages Goodreads thinks the book has.\nThere’s nothing complicated about what I did here, but it was just some simple problem I wanted to solve using code. Enjoy.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Looking at the Blues Wireless Platform",
  "date":"Sat Oct 09 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1633824000,
  "url":"/posts/2021/looking-at-the-blues-wireless-platform/",
  "content":"I love working with microcontrollers; I got started early with the Arduino and Particle Platforms as well as Raspberry Pi (yes, I know, the Pi is not a microcontroller) and many others. I built a few projects on the Particle platform, but I never really got into the Internet of Things (IoT) space. Me hacking around with microcontrollers and single-board computers isn't necessarily the IoT space.\nI recently learned about Ray Ozzie's latest project: Blues Wireless (https://geekwire.com/2021/ray-ozzies-telecom-startup-blues-wireless-raises-22m-bill-gates-others/) and quickly ordered some hardware and got to work learning how to use it. IoT platforms are usually either a software only solution (running in the cloud) or a combined hardware and software solution. Blues Wireless is the latter. The purpose of this article is to give you my take on the platform, and I'll likely publish additional articles here or elsewhere showing you how to use it for different types of projects.\nNotecard and Notecarrier\nBlues' primary hardware product is the Notecard, a tiny wireless device with a processor, some sensors, and an interface that allows other hardware devices to use it to send and receive data to and from the cloud.\n\nNote:  Image 'borrowed' from the Blues Wireless web site at https://blues.io.\nAccording to the data sheet, Notecard is:\n\nA drop-in embeddable data storage and transport module for cellular IoT products, pumping JSON-formatted or binary data (&quot;Notes&quot;) bi-directionally between device and cloud:\nJSON from/to MCU application using I2C, Serial, or USB.\nJSON to/from your cloud app using HTTPS.\nJSON is auto-tagged with date/time, tower, and GPS locations.\nA removable and field-upgradable 30mm x 35mm system-on-a-module (SOM).\nA cellular device without the monthly fees.\n\nThe product page also says:\n\n500MB and 10 years of cellular connectivity included\nGlobal cellular over LTE-M, NB-IoT, or Cat-1\nSecure “off the internet” communications from device-to-cloud\nLow-power hardware (~8µA when idle), power-conscious firmware\nEmbed with onboard M.2 Key E connector or via a companion board\nUnmatched developer experience and JSON-based API\n\nAs you can see from the specs, Blues thought very carefully about what they built and fit into this small card everything you need for many IoT applications.\nThe game changing aspect of this is that the Notecard includes 500MB of data transfer and 10 years of cellular connectivity. There’s no monthly fees for cellular data, you spend between $49US and $69US for the Notecard and get cellular data coverage for the device for 10 years. I don’t know what happens if you try to use more than 500MB over those 10 years, but as long as you’re smart and careful about how you use the provided data plan you should be OK.\nFor some applications, all you need is the Notecard. If, for example, all you wanted was an asset tracker, you can build one using the accelerometer and GPS sensors along with the wireless radio. All you would have to do is power it up, set the device’s configuration via the command-line tools, and you’re all set - no coding required.\nLet me explain…\nThe Notecard has a processor, some memory, some sensors, and a wireless radio with loads of data transfer capacity. It is essentially a cellular microcontroller without the ability to program the processor directly. Instead, Blues provides an interface customers can use to configure and control the device externally using the supported USB, Serial, or I2C interfaces.\nTo configure the device, you use a connected device to pass JSON messages to the Notecard through one of the supported interfaces. Firmware on the device parses the JSON messages and makes the appropriate local configuration changes or performs the necessary actions based on the contents of the JSON message.\nUsing one of the Notecarriers, you can connect the Notecard to a computer using a USB cable the poke and prod the device with JSON messages over a command-line interface (CLI) or through a browser console.\nThere’s even Notecarrier devices for Adafruit Feather compatible devices and Raspberry Pi; with those devices you configure the Notecard using an I2C interface through your device’s custom code (which I’ll talk about a little later).\nThe JSON API is very robust, offering a lot of different options for configuring the Notecard. I haven’t yet learned everything it can do, but you can configure how frequently the device wakes up to collect data and how frequently it sends the data over the network. You can even configure it to sleep periodically and how frequently it checks for new data to download over the network.\nI’m not going to describe all these options, you can find documentation for the capabilities here: https://dev.blues.io/reference/notecard-api/card-requests/. And for a complete tutorial on turning a Notecard into an asset tracker, refer to the Asset Tracking tutorial. https://dev.blues.io/notecard/notecard-guides/asset-tracking/.\nNow, if you want t",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Andy Doro Word Clock Update",
  "date":"Mon Aug 09 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1628553600,
  "url":"/posts/2021/andy-doro-word-clock-update/",
  "content":"When I first discovered Andy Doro's Word Clock project, I immediately fell in love with it and knew I had to build one. I quickly downloaded everything I needed, then ordered the enclosure pieces from Ponoko.\n\nThe clock ran in our guest bathroom for more than a year before I noticed that the time was off. Looking into things, I realized that the temperature change in the bathroom (my son takes loooooong, hot showers) and the temperature sensitivity of the real-time clock (RTC) caused the time to shift.\nI started looking for ways to improve this project so the time would stay accurate, so I decided to fork the project and rebuild it using a Wi-Fi enabled Adafruit Feather board and Network Time Protocol (NTP) to allow the project to periodically reset the local RTC to the correct time over the Internet. I also selected an RTC FeatherWing (add-on board for the Feather) that doesn't have the temperature sensitivity of the earlier project.\nThe Feather board has a different footprint than the Adafruit Trinket board originally used for the project, so I engaged Muzammil Patel on Fiverr to update the enclosure drawings to accommodate the microcontroller change. I also learned that even though Adafruit published a specification for the Feather platform, the Espressif-based Feather boards have a slightly different footprint which made accurately updating the enclosure a challenge.\nI completed the updated project assembly last night and published the forked repository this morning on GitHub.\nWith that work done, I've started working on a wall mounted version of the clock. I have the hardware and software all working, now I have to just start assembling the clock. I'll publish the results as soon as I'm done.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino"
  
  ]
  },

  {
  "title": "Implementing Custom Pipes in Ionic",
  "date":"Sun Jul 18 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1626652800,
  "url":"/posts/2021/implementing-custom-pipes-in-ionic/",
  "content":"Earlier this year, I worked on a desktop app project using Ionic where the app imports a CSV file and does some processing on it. After I parsed the CSV file data using Papa Parse (https://npmjs.com/package/ngx-papaparse) I wanted to display the parsed data back to the page so the user could validate that it parsed correctly.\nI knew what I needed: something that built a comma-separated list in an array so I could easily render it in Ionic. Now, I knew Ionic (and Angular) had a pretty powerful pipes capability where you pass data through a pipe to transform it as its rendered on the page.\nI'd worked with Pipes in an earlier version of Ionic, but when I tried to apply my previous solution to the latest (I don't even know what the latest Ionic version is, 6?), it just didn't work. I looked around on Stack Overflow and the Ionic Forums and found different suggestions on how to make it work, but no complete example to work from. I'm sure the solutions were there, but these quick one sentence suggestions for how to fix the issue I had didn't tell me exactly where everything went - and I needed to know exactly where to put things to make it work.\nI started out with a stand-alone sample application; I always learn better working with real data on a clean slate, rather than trying to poke new tech into an existing application. Once I get it working, its much easier for me to shoehorn the new code into the existing app.\nHere’s the output of my sample application; you can find the complete sample application at https://github.com/johnwargo/ionic-pipes-example.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Web Development"
  
  ]
  },

  {
  "title": "Using the Arduino NTPClient Library",
  "date":"Sat Jul 17 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1626566400,
  "url":"/posts/2021/using-the-arduino-ntpclient-library/",
  "content":"As I mentioned in my previous post, I have a version of Andy Doro’s Word Clock running in my house. I had some issues with the real-time clock (RTC) keeping time correctly, so I decided to rebuild the clock using a Wi-Fi enabled device and the Network Time Protocol (NTP) to keep my clock’s local time synchronized with reality. I’ll write more about that project once I’ve completed it.\nAs I started working on my updated project, I discovered that the Arduino team maintains (well, used to maintain) an NTP Client library called NTPClient (https://github.com/arduino-libraries/NTPClient) that would work for my project. The library is pretty easy to use, however it’s woefully under-documented. There’s a very simple readme in the project repository with an overly simple sample sketch and a vague reference to only one of the functions exported by the library.\nSadly, there are a couple of pull requests (PR) in the repo for documentation changes, but those aren’t getting any love from the team.  I thought about proposing some updates to the docs in order to clearly document how the library works, but realized they’d likely not get published. However, I may go back and submit them later.\nAs I tried to learn what the library did, I studied the source code and I now have a better understanding of the inner workings of the library. The purpose of this post is to share some of what I learned.\nNote: The library expects the device running the sketch (and using the library) to have a valid network connection (typically over Wi-Fi). You can only retrieve the time from a network time server (using NTP) if you can connect to the server over the network. So any sample code you see using the library will connect to Wi-Fi before doing anything else related to the NCPClient library.\nTo use the library in your sketch, you must add to libraries:\n\nThen, you must initialize two variables:\n\nThe NTPClient object supports several initialization options (multiple constructors). The default one shown in the example code uses default values for several configuration options. No matter which approach you use, you must provide a Wi-Fi UDP object to the constructor as shown in the example.\nUDP stands for User Datagram Protocol which is a communications protocol that enables network devices to exchange messages. Rather than designing its own communication protocols between the client and server, it just uses a standard one. You don’t have to do anything with UDP except to create the ntpUDP object as shown in the example and pass it to the NTPClient constructor.\nThe default constructor also configures the client to use the default NTP server pool (described below) and sets an update interval of 1 minute (more on that later as well).\nIf you look at the sample application in the NTPClient repository’s readme file, you’ll also see this code in the sample:\n\nThis highlights another supported constructor for the NTP client. In this case, it shows how you can specify a different time server pool, a time offset, and an update interval. Unfortunately, the text doesn’t explain what any of this means, so let me see if I can fill in the blanks:\nTime Server Pool: To make it easier for applications to retrieve the current time using NTP, the community created a ‘big virtual cluster of timeservers’ online. Rather than having to know the specific address/name for a time server, you can point your client application to a pool of servers and through Internet Magic get connected to any of the servers in the default pool. You can also specify a specific pool like they do in the example depending on your location (for example specifying the pool for Europe). You can read more about Time Server pools at  https://ntppool.org/en/. Unless you have a specific need to specify a pool, I’d just leave things at their default, but I’m not an expert on this topic.\nTime Offset: Depending on the application and the time zone you’re in, you may want to set a time offset as well. The time offset specifies the number of seconds by which to adjust the retrieved time. The 3,600 seconds shown in the example is one hour (60 seconds times 60 equals an hour) telling the NTPClient to add an hour to every retrieved time value. The reason this option exists is to enable you to adjust the time for your current time zone. For example, I’m in US Eastern Time (GMT-4) which means I’m 4 hours behind Greenwich Mean Time (GMT) and the time offset for my location would be -14,400 (-4 * 60 * 60).\nUpdate Interval: This parameter seems to indicate that you can specify how frequently the NTPClient updates its time over the network, but that’s not the case. The NTPClient doesn’t automatically update the time from the network. What this parameter does is control how frequently the NTPClient can update the time, and this is where it gets a little weird (and why I wrote this article); I’ll explain this more throughout the remainder of the article.\nIn your sketch’s setup function, you’ll initialize the NTPCli",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino"
  
  ]
  },

  {
  "title": "Word Clock Time Issues",
  "date":"Tue Jul 13 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1626220800,
  "url":"/posts/2021/word-clock-time-issues/",
  "content":"I'm a big fan of Andy Doro's Word Clock (https://andydoro.com/wordclockdesktop/) project. As soon as I saw the project highlighted in Make Magazine, I immediately ordered the parts and assembled the desktop version of the project. The clock's been running in our guest bathroom for more than a year now and I recently noticed that the clock wasn't keeping time very well. It was about 20 minutes fast.\nWell, I grabbed the source code and looked for an easy way to fix this. The original project is based on the Adafruit Trinket device which doesn't have a Wi-Fi connection, so it can't get it's time through Network Time Protocol (NTP). Instead, the project has the following code which tries to initialize the realtime clock (RTC) and, if it can't (because there's no time stored in it), it sets the clock to the compile date/time for the currently running sketch.\n\nThis is a great solution for initially setting the clock, since the first time you run the sketch it automatically sets the clock with the current time. Unfortunately, this code doesn't work for my situation.\nSo, I came up with two potential solutions for this problem. I implemented the first one and it worked great for me. The second one sounded great on paper, but it wouldn’t work, I’ll describe it later. So, the only solution I have is to change the sketch’s code so it lets me reset the clock at will.\nThe first thing I did was add a new define to the sketch:\n\nIt's commented out right now because I only want it uncommented (applied) when I want to reset the clock.\nNext, I took the code that sets the RTC to the compiled sketch date/time, and moved it into a separate function:\n\nFinally, I removed this code from the setup() function:\n\nAnd replaced it with this code:\n\nWith that in place, I uncommented the define line:\n\nThen I compiled and deployed the code to the device. When that finished, my clock’s time was reset to the current time (win!). Next, I commented out the define line:\n\nThen compiled and deployed the code a second time (with the define commented out) and the code’s back to its default behavior.\nNow this isn’t a perfect solution, but its the best one I could come up with. I submitted this change as a PR to the original repo, but I’m not sure if Andy is accepting contributions.\nI thought perhaps I could pull the battery and let the RTC memory clear, but as soon as I put the battery back in and power it up, the clock will set to the compile date/time for the sketch. The only way to make this work is to wipe the Trinket device, pull the battery, then compile and deploy the latest version of the sketch to the device. Since the clock is already assembled, and I’d have to take apart the case to do this, I decided to abandon that approach. That just seems like too much work to me.\nI could deploy a new version of the sketch to the device, then pull the battery and put it back in again. That would work and the time would only be off by however long it took to pull the battery, put it back in, and power-on the device. Still more work than I want to do considering I’d have to disassemble the enclosure to get at the battery.\nI have the hardware to build a 12-inch version of the Word Clock; once I get that one built, I’ll publish the details somewhere.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino"
  
  ]
  },

  {
  "title": "Simplifying Moddable Deployments",
  "date":"Thu May 20 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1621555200,
  "url":"/posts/2021/simplifying-moddable-deployments/",
  "content":"As I mentioned in my previous post, the Moddable SDK is a command-line driven SDK. It really has to be that way because it's an SDK that works with a variety of devices and each device platform has its own SDK which is usually also command-line driven.\nEach supported platform has its own environment setup as well. For example, the Espressif platform uses Python and other client side tools and there are special PATH settings needed on the system when working with that platform. Since many developers may switch between hardware platforms on different projects, there's commands developers must configure and use to switch between the different hardware SDKs.\nAs I worked with the Moddable SDK, I realized that depending on your project's configuration (host and module folders) and the selected hardware platform, you're using the exact same Moddable commands but with different command-line options. I realized that there was a way to simplify the commands and eliminate a lot of the repetitive typing you had to do.\nLet me give you some examples…\nWhen you’re deploying a host module on a device using the Moddable SDK, you’ll use the following commands:\n\nThe first command switches the terminal window to the folder hosting the files (in this example it is the host folder), and the second command invokes the Moddable SDK’s mcconfig command to build and deploy the Moddable core application and host module to the selected device.\nAs I’m testing the host module on a specific device, the commands change little and every time I start my development environment, I have to type the same commands the first time I use them. I can use the command stack feature of my terminal program to repeat the commands later, but when I first open the terminal window, I’m typing those commands every time.\nIf I’m building my project for multiple devices, the commands change a little. Say for example I want to install the host on a M5Stack Fire device, the commands look like this:\n\nAll that changes is the parameter passed in the platform option (-p).\nWhen I want to deploy the HelloWorld module to a device already running the host module, the commands change just a little:\n\nI have to change to a different folder and the mcconfig becomes mcrun. And, of course, if deploying the same module to the M5Stack Fire device, the command changes to:\n\nModdable Project Options\nA Moddable project could have all of its JavaScript stuff in the host module, but then deploying the host is a very time consuming process because of all the work the SDK has to do to build the core application for the target device plus deploy the JavaScript code as well.\nMost Moddable projects consist of a host module plus one or more additional JavaScript modules. Developers deploy the host module less frequently (since that takes so long) and do most of their work in JavaScript modules which deploy pretty quickly.\nThis means that a Moddable project typically has a host folder (the folder holding the host module) and additional folders for each of the JavaScript modules used by the project.\nRecognizing The Patterns\nIt didn’t take me very long to recognize the patterns in this process and realize that I could simplify this dramatically while still giving Moddable developers the flexibility they need to support complex Moddable projects deploying to multiple target devices.\nHere’s what I learned:\n\nA Moddable project can have multiple folders (one for each module).\nA Moddable project can have only one host module.\nA Moddable project can have zero or more, I’m not quite sure how to say this, non-host modules\nDevelopers only use the Moddable mcconfig command for deploying host modules.\nDevelopers deploy most modules using the Moddable mcrun command.\nThe only command-line options for mcconfig and mcrun that really changes during development is the platform parameter (specifying which hardware device family to which you’re deploying)\n\nSo I started thinking, what if I abstracted away the complexities of the project into a set of simple commands a developer could use to deploy Moddable modules flexibly without having to remember which Moddable SDK commands to use and which command-line parameters to use?\nTo accommodate that I’d need some sort of project-specific configuration file that described the different folders in the project (which folders held JavaScript modules and which one was the host module for example).\nI’d also need a configuration file (or a section of a configuration file) to describe the different hardware platforms I’m using for the project.\nWith those three components, I’d have a simplified way to manage my Moddable projects and deployment to a variety of devices.\nIntroducing Moddable Helper\nBased on the requirements listed at the end of the previous section, I created a node package called Moddable Helper. When you install the module on your Moddable development system (it works on Linux, macOS, and Windows), it adds a mddbl command you can use to streamline your command t",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Moddable, Windows, & Visual Studio Code",
  "date":"Wed May 19 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1621468800,
  "url":"/posts/2021/moddable-windows-visual-studio-code/",
  "content":"I've been working a bit lately with the Moddable platform; I set up their SDK on my macOS and Windows systems, but for several reasons I prefer to code on Windows unless I have to use macOS. The Moddable SDK is very command-line heavy (for reasons I agree with) and as I started coding Moddable JavaScript projects in Visual Studio Code, I realized that there are some tweaks I can document here that may help other Moddable developers using Visual Studio Code on Windows.\nEnvironment Setup\nI'm primarily using Moddable with Espressif devices (specifically the ESP32 devices from Moddable and M5Stack) and the Moddable ESP32 installation instructions show how to configure a command-line environment setup with all of the environment variables and PATH entries you need to execute Moddable SDK instructions that invoke the Espressif SDK.\nThe idea is that you'll double-click a shortcut to open a properly-configured terminal window (what Windows calls a Command Prompt) and execute all of the Moddable SDK commands from there.\nThe problem for my environment is that I want to do all of my work inside Visual Studio Code (I'm going to start calling it VSC from here) and VSC has its own terminal built in that I can use instead of switching to an external one.\nOn Windows, the Moddable SDK uses some tools from Visual Studio, and one of the things that comes along with that is a Start menu shortcut that opens a terminal window and executes some commands to configure the terminal window for the Visual Studio tools. On most systems, that shortcut points to the following file:\n\nThe Espressif SDK also creates a shortcut that properly configures a terminal window for the Espressif SDK, it executes the following:\n\nWhat Moddable tells you to do is update Espressif shortcut so it instead executes both commands when you click it:\n\nWhat I did was make a copy of the Espressif SDK shortcut and modified that one so I’d still have a clean Espressif SDK environment if I wanted it later.\nUnfortunately, none of this does me any good in VSC, since VSC can’t access the terminal window directly (it has its own). What I did instead is break those commands out into a command file (an executable text file with a .cmd extension) called mod-set-env.cmd (https://gist.github.com/johnwargo/9cd1a6c15e98a2ef8a6adeed927f0a7f) that looks like this:\n\nI originally included this command file in my Moddable project folder, but I quickly realized I didn’t want to have to copy that file around into every project, so I put it in a folder full of other random executables that I happened to have on my PATH environment variable. This allows me to execute this file from anywhere.\nWith the file in place, every time I launch VSC to work on a moddable project, I open the VSC terminal windows and execute mod-set-env.cmd and VSC is all set up to work with the project.\nUnderstanding the Command File\nThere’s a lot going on in this simple command file, so I thought I’d explain the different parts of it.\nAt the start of the file is a commented-out line that looks like this:\n\nWhat this does is sets an environment variable the Espressif SDK uses to identify the port number for a connected device. Apparently the SDK is pretty good at figuring this out on its own, but if it can’t, you can uncomment this line (remove the REM at the start of the line) then specify the port number for your device and the SDK should find it.\nI disabled that line since on my system the SDK has no issue finding connected devices.\nNext, the command file checks to see if a specific environment variable is set:\n\nThe command file sets the VCToolsVersion environment variable when it executes, so I added this check to keep me from running the command file twice. If the environment variable is missing (empty) then the command file executes all the steps to configure the environment:\n\nWhich should look familiar since it’s the same code the Moddable folks told you to use in your modified shortcut.\nWhy did I pick the VCToolsVersion environment variable? No reason. I randomly picked something in the environment that I knew only existed after I configured a terminal window for the Visual Studio development environment. I just needed some way to know I’d already executed the command file and this environment variable check worked the first time.\nIf the environment variable is already set, then the command file warns you and exits:\n\nThe echo: by itself enters a blank line in the terminal window.\nDeploying to Devices\nNow, when it comes to deploying JavaScript code to devices, the Moddable SDK  has specific commands you must use depending on whether you’re deploying a Host or Module. Since the two commands are very similar (and have the same command parameters), I decided to create command files for each. Here’s the code I used to deploy the host model; I put in a file called deploy-host.cmd in my Moddable project folder:\n\nThe code assumes the host project is in a folder called host (it is, and I’m guessing will normally b",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Displaying Build Information in ReactJS",
  "date":"Fri May 14 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1621036800,
  "url":"/posts/2021/displaying-build-information-in-reactjs/",
  "content":"In an earlier article, I showed how to access build information in an Ionic application. When I created the solution for Ionic, I created a similar solution for ReactJS apps; I describe that solution in this article.\nManipulating the Project Configuration File\nReactJS projects use node-based tooling like most web-based frameworks, so they already have an easy to update place to maintain the application's version number - in the project's package.json file. Here's a stripped-down version of the package.json file from a new project I just created:\n\nNotice the version property, setup and ready for use.\nNow, what I needed next was a simple and automated way to update that value every time I built a new version of the app. Fortunately, the Node Package Manager (npm) already has a feature that increments the value for you:\n\nWhen you execute that command from the Ionic project folder, it automatically increments the patch version (the final value in the version string):\n\nHow cool is that?\nAvailable options are major, minor, and patch. Updating the major version increments the first value in the package.json file’s version property. Updating the minor version increments the second value in the package.json file’s version property. You’ve already seen what patch does. Here’s links to the docs: https://docs.npmjs.com/cli/v7/commands/npm-version.\nThe React project configuration file already has an automated build process:\n\nYou can easily modify it to automatically update the version number at build time using this instead:\n\nGenerating Build Information\nUnfortunately, as far as I can tell, a React project doesn’t have access to the project’s package.json file at runtime, so I needed a way to access the version number in my application.\nSince React projects already use node and npm, I decided to create a simple node module that takes the version number from the package.json file and copies it into a file in the React project; the module is called react-build-info.\nYou have to install it globally since you can’t easily execute the module locally (that I could figure out anyway), but when you execute it, it creates a file called buildinfo.js in the project’s src folder and copies over the version number from the package.json file and adds the date/time stamp for the build event. Here’s the file:\n\nTo execute the module every time you do a build, just update the build entry in the project’s package.json file:\n\nDisplaying Build Information In the App\nNow that I had the build information generated and available in the app, it's time to use it in the app. What I wanted to do was display the app build information (version number and build date) on the app’s login page, but I decided instead to simply display it in the console at startup.\nTo do this, I opened the project’s src/App.js file and added the following import statement to the top of the file:\n\nThis loads the contents of the file into a buildInfo variable I can use in my app like this:\n\nAnd there you have it, a quick and painless way to automatically update React app build information accessible from within the app.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Web Development",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "JavaScript Microcontrollers",
  "date":"Thu May 13 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1620950400,
  "url":"/posts/2021/javascript-microcontrollers/",
  "content":"For many years now, I've worked extensively with a variety of microcontrollers and single-board computers. Since I was a small child, I always had an interest in electronics projects and the modern catalog of these computing devices gives me lots of opportunities to play and build things.\nIn my professional life, for most of the last few years I've coded primarily using JavaScript and web technologies. My work on the Apache Cordova project and associated books plus my day job for products in the Apache Cordova and mobile development space kept me mostly in JavaScript code (for hybrid application and JavaScript-driven native application work). Because of this, I'm always on the lookout for interesting JavaScript microcontrollers.\nTessel\nI did some work many years ago on the Tessel platform; Tessel, in their own words, is “Tessel 2 is a robust IoT and robotics development platform. Leverage all the libraries of Node.JS to create useful devices in minutes with Tessel.” You code projects in JavaScript and the platform’s node engine executes them. You can even build and deploy web server applications to the device. I built and published several application projects for the Tessel platform: two versions of a weather station (https://github.com/johnwargo/tessel_weather_station and https://github.com/johnwargo/tessel_m2x_weather_station) and a garage door controller (https://github.com/johnwargo/tessel_garage_door_controller).\nCoding for the platform is easy, you write your JavaScript code in your favorite editor, then use the Tessel command-line interface (CLI) to provision the device and deploy your code. You can even configure Wi-Fi network settings on the device using the CLI (instead of hard-coding them in your source code).\nFor hobbyists, Tessel is just an open source prototyping platform, they don’t produce a suite of different devices, instead, they produce a single reference device you can use to prototype your project, expecting that you’ll embed the platform in any commercial device you produce from the prototype. They also offer a small catalog of sensors and add-on modules (like the relay I used for my garage controller project and the weather sensor I used for my weather station projects) you can easily plug into the board.\nI really enjoyed working on the platform and wish I could do more with it, but it’s prototype-only approach kept me away. I didn’t have any interesting hardware projects I wanted to build from scratch, and when I did, I selected the ESP32 platform for reasons I’ll explain some day.\nEspruino\nAnother popular JavaScript hardware platform is Espruino. Espruino produces a variety of device formats which gives you a lot of flexibility for different types of projects.\nCoding for Espruino is easy, you can use their CLI to deploy code to devices just like I described for Tessel above. They also offer a browser-based integrated development environment (IDE) they call the Web IDE. The Web IDE allows you to code your application, then push it directly to devices from the same interface; you simply plug the device in via a USB cable and work iteratively with the device through the browser.\n\nI’ve purchased several Espruino devices over the years, but haven’t done anything with them. I just haven’t found something interesting I want to do with them. I played around many years ago with the Espruino Pico device, it’s a USB stick with a microcontroller in it, but again struggled to find an interesting purpose for it.\nOf special interest to me is the Espruino Puck.js which is essentially a JavaScript programmed Bluetooth button with LEDs and other stuff like sensors inside. Again, I keep looking for something to do with this platform and the puck is such an interesting and capable device that I’m sure something will come up.\nThe biggest issue I have with the platform, and likely one of the reasons I’ve kept away from it, is that the boards are rather expensive. The small and simple Espruino Wi-Di device is $35US which is more than three times more expensive than the much more capable ESP32 device. I keep hoping the prices will drop on these devices, especially not that there are a whole lot of sub-$10 devices out in the market today, but Espruino devices remain a premium choice.\nModdable\nMy most recent experimentation with JavaScript devices is on the Moddable platform. I think Moddable has incredible potential, for several reasons I’ll explain later, but I’m really struggling to be productive on the platform.\nMany years ago I was at a trade show (I can’t remember which one) and met a guy named Peter promoting a platform called Kinoma they were pre-release, but their JavaScript devices looked really cool so I ordered a few then waited patiently for them to ship. After they arrived, I never got around to playing with them, but by the time I did, the company had shut down. Sigh.\nI’d check in every so often looking to see what the team was doing and a while back discovered that Peter and friends from Ki",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Displaying Build Information in Ionic Applications",
  "date":"Thu May 13 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1620950400,
  "url":"/posts/2021/displaying-build-information-in-ionic-applications/",
  "content":"Introduction\nThis winter, I worked on a project where I had to build a web-based sales automation tool and, for different reasons, I decided to do the project using Ionic. The project was for desktop browsers, and while Ionic wasn't the best choice for a desktop app, it's the web framework I know the best, so that's what I used.\nSince I knew the audience for the app, I knew I'd have to build in specific features to make the app easy to support for non-technical users. One of the things I wanted to make sure I had was the app version and build date easily accessible in the app. I looked around to see if anyone had an existing solution for this, and I found a lot of people looking for a solution but no solution. I decided to make one.\nManipulating the Project Configuration File\nIonic projects use node-based tooling like most web-based frameworks, so Ionic projects already have an easy to update place to maintain the application's version number - in the project's package.json file. Here's a stripped-down version of the package.json file from a new project I just created:\n\nNotice the version property, setup and ready for use.\nNow, what I needed next was a simple and automated way to update that value every time I built a new version of the app. Fortunately, the Node Package Manager (npm) already has a feature that increments the value for you:\n\nWhen you execute that command from the Ionic project folder, it automatically increments the patch version (the final value in the version string):\n\nHow cool is that?\nAvailable options are major, minor, and patch. Updating the major version increments the first value in the package.json file’s version property. Updating the minor version increments the second value in the package.json file’s version property. You’ve already seen what patch does. Here’s links to the docs: https://docs.npmjs.com/cli/v7/commands/npm-version.\nThe Ionic project configuration file already has an automated build process:\n\nYou can easily modify it to automatically update the version number at build time using this instead:\n\nGenerating Build Information\nUnfortunately, as far as I can tell, an Ionic project doesn’t have access to the project’s package.json file at runtime, so I needed a way to access the version number in my application.\nSince Ionic projects already use node and npm, I decided to create a simple node module that takes the version number from the package.json file and copies it into a file in the Ionic project; the module is called ionic-build-info.\nYou have to install it globally since you can’t easily execute the module locally (that I could figure out anyway), but when you execute it, it creates a file called buildinfo.ts in the project’s src/app folder and copies over the version number from the package.json file and adds the date/time stamp for the build event. Here’s the file:\n\nTo execute the module every time you do a build, just update the build entry in the project’s package.json file:\n\nDisplaying Build Information In the App\nNow that I had the build information generated and available in the app, it's time to use it in the app. What I wanted to do was display the app build information (version number and build date) on the app’s login page, but I decided instead to simply display it in the console at startup.\nTo do this, I opened the project’s src/app/app.component.ts file and added the following import statement to the Top of the file:\n\nThis loads the contents of the file into a buildInfo variable I can use in my app like this:\n\nAnd there you have it, a quick and painless way to automatically update Ionic app build information accessible from within the app.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "JavaScript",
  
    "Web Development",
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Reviewing the Wrong Book",
  "date":"Mon Apr 19 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1618876800,
  "url":"/posts/2021/reviewing-the-wrong-book/",
  "content":"I was up on Amazon this morning and I noticed the following review of my latest book (Learning Progressive Web Apps):\n\nThough the author is clearly passionate about PWAs, the writing is poorly edited and the explanations are incomplete. Examples are repeated and reprinted 2-3 times, as are instructions for running sample code.\nDespite being a 200+ page book on PWAs, the author delegates the most crucial definitions and explanations to other resources. Precise information about how the API is structured is completely absent from the book — e.g., the service worker container is never even mentioned. Instead, you get unidiomatic examples and shallow explanations covering a fraction of the API. This book reads more like a series of blog posts written by a hobbyist than a programming text.\n\nI know it's hard to get your ego out of the way of a bad book review, but in this case, I'm pretty sure the book review isn't for my book. This isn't the first time this has happened on Amazon, but in the past, Amazon would let me reply to the reviewer and set the record straight. On today's Amazon, that option is no longer available.\nSo, looking at the review, the reviewer says the book is poorly edited and explanations are incomplete. That alone tells me this reviewer didn't read the book since the book went through several thorough edits - there's no typos, misspellings and all of the content is clear and concise.\nAs for incomplete explanations - over explanation is actually a problem with some of my books (like this one), I make deliberate effort to make my explanations as complete as possible, that’s my writing style. I always write from the perspective that I'm telling a story to someone who knows nothing about the topic (expecting that a more experienced reader will skip the introductory material).\nExamples repeated and reprinted 2-3 times? Absolutely not, not this book. Each example appears only once in the book. Since the book's sample apps build on previous examples, there are places where previous code is shown as I build new functionality on it. That's the only way to do that type of learning - build on top of previous learning. Instructions for running sample code is repeated throughout the book once per chapter because I can’t know that the reader is jumping around in the content, so I make the content as complete as possible so that the reader won’t get lost. Authors receive contracts form their publishers for a book of a certain length, in many books authors repeat the instructions for every sample and publish the boilerplate code for every example just to drive up the page count for their book.\nAs for “the author delegates the most crucial definitions and explanations to other resources” that again proves that the reviewer didn’t read my book since there is no place in the book where a reader is referred to another resource for details. I link to reference materials, but everything, literally everything you need to learn how to code PWAs is in the book.\nI don’t understand what the reviewer means by “Precise information about how the API is structured” - what API? I have absolutely no idea what they mean.\nThey are right though that I didn’t make any mention of the service worker container - the book has a whole chapter on Service Workers and everything you need to know about how to work with them is in there - without any need to mention that there’s a container object that hosts all those capabilities.\nAnyway, apologies for the diatribe here, but I can only hope that someone who reads that incorrect review on Amazon will somehow find this and see that the reviewer apparently didn’t read my book or didn’t understand it very well. Does the book have faults? Absolutely. Is it well represented in the review? Nope.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Firebase Functions Deploy Helper",
  "date":"Fri Apr 02 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1617408000,
  "url":"/posts/2021/firebase-functions-deploy-helper/",
  "content":"As I mentioned in an earlier post, I worked on a project this year that used Firebase Functions against a Google Cloud SQL database. As I worked with Functions, I quickly started bumping up against deployment quotas.\nMy project has 61 functions, and if I try to publish all of them, Firebase craps out and will only publish a subset of the total. I quickly realized that if I published the whole batch twice, all of them would usually publish.\nIn conversations with the Firebase Support team, they indicated that there was nothing I could do except to publish my functions in batches. When I'm coding in my project, I'm jumping around from function to function and it's too much trouble to reliably track which functions I modified. I decided instead to use automation and a little Node module to solve the problem for me.\nThe module I created is called Firebase Functions Deploy Helper When you install the module, it installs a command called ffdh which simplifies batch installation of a Firebase project's functions.\nYou can deploy in batches, deciding at runtime how many batches you want to use, then deploying each batch separately. You can also use search to select the functions to deploy, searching for functions using a search string against the start or end of the function name.\nRead the project readme file to learn more about how to use the module.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Talking Myself Out of a Job",
  "date":"Thu Apr 01 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1617321600,
  "url":"/posts/2021/talking-myself-out-of-a-job/",
  "content":"As I mentioned in yesterday’s post, I have another hiring story to tell, and here it is. The way I portrayed it in yesterday’s post and in the article title above you may think this is a sad story, that I did something horrible that cost me a job opportunity. That’s not the case; what happened was I very honestly answered a question during an interview and that, well, killed the job opportunity for me, but not in a bad way. Let me explain...\nThe Setup\nI applied online for a Principal Program Manager role for a large software company; they have a public service that millions of people use, and they were looking for a PM to shepherd some technical, and likely customer impactful, infrastructure changes they planned for the service. There wouldn’t be a lot of feature development work in this position for a year or more, but the problems we encountered during that first period would be thorny, and for that reason I was very interested in the position.\nThis is the same position I wrote about where I received an email from the Recruiter letting me know he was interested in looking at me for the position, but all of my response emails went into his spam folder. Once I got past all the spam folder issues with the recruiter, I heard back that the hiring manager wanted to talk with me.\nI had the initial conversation with the hiring manager and I left feeling that it would be a great job to have and looked forward to the next step in the process. The hiring manager expected to select a few candidates to put through the next step in the process and I believed I’d be one of them.\nA few weeks later, they scheduled my ‘Day Of Interviews’ (ominous music plays) interviews.\nThe Initial Interviews\nThe Day Of Interviews started with a follow-up call with the hiring manager. We talked more about the position, and I got a good feel for the team and what the day to day would look like. Still interested in the job.\nThe next two interviews were with existing PMs putting me through the PM wringer. One was a PM manager on a partner team, and the other was with a Senior PM on the team I’d join if I earned the position. Both interviewers asked me scenario-based questions around PM topics and I think I did pretty well in the conversation mostly because I’ve been around for a while, had several PM positions in the past, and think I know what I’m doing. I do, really.\nThe Flashback\nI have to be very careful at this point because the part of the story I’m about to tell will make you think that I don’t want another PM position. That’s not true. I start a new Principal Product Manager position on Monday and I’m very excited about it.\nBefore I lost my job at GitHub, I spent a lot of time thinking about the types of jobs I’d be interested in if, you know, I lost my job at GitHub. Yes, I did know I would lose my job at GitHub; GitHub and I were… incompatible. Well, that’s not entirely true, GitHub should have been an excellent opportunity for me, but it just didn’t work out that way. That’s all I’m gonna say about it.\nI dug out a pad of paper and pencil, sat in my favorite office chair, and spent an hour or so brainstorming with myself (can you brainstorm with yourself?) about which types of jobs I should pursue.\nAt the top of the list was PM positions. My last few jobs (I’ve had a lot of them) were PM positions and I’m very comfortable and happy being a PM. PMs help bring products and product features to market and I like doing that.\nBringing in a close second was Evangelist positions. I’m probably happiest in evangelism roles since it keeps me close to developers and lets me write code, white papers, and technical articles plus present technical topics at conferences and customer meetings. All of those things make me very happy. PMs get to write and present, but don’t do so much code writing (and Engineers typically scoff at PM-generated code).\nI applied recently for a few evangelism jobs and never got anywhere with them. Honestly, I don’t think I’m cool enough anymore to be an evangelist. When I was younger, I had a goatee (still do but it's VERY grey) and that made me cool enough to be a product evangelist. A Goatee or pony tail were the keys way back when to successful product evangelism roles. Nowadays I’m an old, bald, grey-haired guy, which isn’t ‘evangelism cool’. I recently started wearing hats more frequently, mostly because I’m bald, so perhaps if I got a really cool hat and started wearing that all the time I’d be cool enough again to be an evangelist. Who knows?\nNext came Software Engineer. Yes, of course, software engineering roles are really, really cool. Lots of hard work. Building cool stuff. People using your stuff. Focused work. But, even though I identify as a software developer and play one on television, it’s been a really long time since my job was writing code. I know a lot of development languages, a lot of server and cloud technologies, and I know how to make award-winning commercial products that work. Hold this though",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Starting a New Job Monday",
  "date":"Wed Mar 31 2021 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1617235200,
  "url":"/posts/2021/starting-a-new-job-monday/",
  "content":"I start a new job on Monday. I've been out of full time work since the end of September, which has been a lot of fun, but its time to get back to work and have steady income and benefits again.\nDuring my time off, I did some interesting things. I completed certification as an OutSystems platform Reactive developer. I tried to complete my CSSLP (Certified Secure Software Lifecycle Professional) certification but failed the exam; that was a tough blow, but at least I focused some energy on development security for a while, so that put me in a good place.\nI did some consulting work for a company, designed and helped build a cloud-based sales automation tool. This gave me an excellent opportunity to learn Firebase Functions and Google Cloud SQL plus I worked on my largest ever Ionic project which really solidified my skills there.\nIn all, losing my job was quite painful, but I used the time to enhance my skills while I looked for new opportunities. I didn't sit on my ass and relax.\nLooking for a job during the Pandemic was hard, but different than I expected. Previous experience and research in the job market made me believe that people didn't get jobs anymore by applying for them online. That turned out not to be the case, I was very active on LinkedIn finding and applying for positions and I got quite a few interviews that way. Knowing someone still pays off more, but I found a nice balance between working with people I know and applying for jobs blindly. As it turns out, I got two offers, one from someone I'd worked for before and another from a company I applied to blindly last year.\nCompanies sure make you work harder nowadays to earn a position. Most companies I dealt with during my job search asked me to perform some sort of task as part of the interviewing process which ended up consuming a lot of my time without benefit. I laughed inside when a company looking to hire me as a manager for some technical writers asked me to do a writing exercise. I thought for sure that availability of 8 books written by me plus numerous public examples of blog posts, documentation articles and the like would be enough, but they asked me to write something anyway.  In another example, when applying for a developer relations position for a company (a job that really interested me), I was really surprised they asked me to do a coding exercise. Again, I thought that my 7 technical books plus numerous blog posts and more than 60 public code repos on GitHub were enough to prove my coding chops, but apparently not. I did learn something about NodeJS development in the process, but I would have preferred that they look at my public body of work rather than make me create something new just for them.\nWhat bothered me the most about this whole job search process is Recruiters lack of responsiveness. I often waited weeks to hear back from recruiters on jobs I interviewed for and that was painful.  In several cases, I didn't get the job I wanted (for whatever reason) but the recruiter assured me that the company liked me and that I should apply for another position. I'd quickly look around for other interesting open positions and apply for them (letting the recruiter know) only to get no response for weeks or more than a month (even sometimes no response ever again). Don't lie to me, if you don't want to hire me that's OK, you're not going to hurt my feelings. But, don't leave me on the hook for weeks at a time when I could be expending job search energy in other ways.\nHow hard is it to reply to an email a few days after an interview series ended and give the candidate an update? Not hard really, but it rarely happened in this recent job search.\nOne of the funniest and potentially saddest issues I came across was for a position I applied for in a big company. The recruiter reached out to me and asked a few questions about my application and I responded in a matter of hours. A week later, nothing - so I sent the recruiter a follow-up email - nothing. Another week goes by and I sent another follow-up email. Crickets. Finally after a few weeks of this with no response from the recruiter I finally got a text message from the recruiter asking if I was interested in the position. Yes, of course I was, I replied, I've been emailing you for weeks now. It turns out, of course, that none of my return messages made it into the recruiter's inbox. Thank goodness for this particular recruiter's efforts, otherwise I wouldn't have a chance to interview for that position (which I didn't get anyway).\nI have one last story to tell - about the time I talked myself out of a job opportunity while speaking with the VP at the end of a series of interviews. Its the first time I really ever knew exactly when I didn't earn the position I applied for.  Perhaps I'll write about that tomorrow.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Interesting Domain Registration Scam",
  "date":"Mon Jan 11 2021 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1610409600,
  "url":"/posts/2021/interesting-domain-registration-scam/",
  "content":"I received an interesting email from this site this morning, a comment by someone who's trying to tell me that this site's registration WILL BE TERMINATED soon. Here's the text of the email I received:\n\nThis wasn't a spam email, but a submission from the site's contact form; a different approach from the other junk I regularly get in my inbox.\nI'm scared to think of all of the people who will fall for this email and plunk down money to renew the domain registration. Looking at the email, the renewal registration URL looks like a reputable domain, except for the '.ga' top level domain (TLD) which should give any recipient pause in every case. The URL includes a query string which makes it look like a valid URL. I didn't click the link, but when I opened the browser to the root domain (https://domain-registration.ga) I saw a generic page prompting visitors to re-register their domain for one year, two years, etc. as shown in the following figure:\n\nUnfortunately this makes it really, really easy for people to give these criminals their money.\nNotice the fake McAfee, TRUSTe and Norton images, falsely claiming validation from trusted companies. They're not links, which they would be in a valid, protected site.\nThis is really dangerous, and I hope people find this and skip clicking the link if they ever get an email like I did today.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "PWA Webinar This Month",
  "date":"Thu Jul 30 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1596153600,
  "url":"/posts/2020/pwa-webinar-this-month/",
  "content":"Next month, I'm delivering a webinar entitled Progressive Web Apps: Enhancing Your Web Apps Using Service Workers (https://oreilly.com/live-training/courses/progressive-web-apps-enhancing-your-web-apps-using-service-workers/0636920409854/); the material for this webinar is based on part of my most recent book: Learning Progressive Web Apps (https://learningpwa.com). Join me if you can; here's a description:\nProgressive Web Apps (PWAs) are the bright future of desktop and mobile applications. There are different ways to look at PWAs, but in general they're interactive web applications built using specific browser capabilities that enable the web apps to work and act more like native apps. Research firm Gartner was so confident in the growth of PWAs that they predicted that 50% of all consumer apps would be PWAs this year. Many of the web applications you currently use are most likely PWAs with Google releasing Gmail as a PWA and Microsoft delivering both Outlook and OneDrive as PWAs this year.\nIn this fast-paced session chock full of technical details, you'll learn how build your own progressive web applications. You'll learn how to make your app installable using web app manifests and some JavaScript code. You'll also learn how to make your web app work in offline mode on compatible browsers using service workers. You'll also learn about all the ways service workers can enhance the capabilities of a web application.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Web Development"
  
  ]
  },

  {
  "title": "Useless Machines",
  "date":"Tue Jul 14 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1594771200,
  "url":"/posts/2020/useless-machines/",
  "content":"Many years ago (I can't remember how many), I bought a Useless Machine kit from Frivolous Engineering. It's this amazing kit that enables you to build a machine that when you turn it on, it immediately turns itself off; a finger pokes out the lid to flip the power switch back to off again.\n\nI bought it so I could build it with one of my children and was pleasantly surprised when Elizabeth wanted to build it with me. We had an amazing hour or so putting this thing together and big laughs every time we turned it on.\nOf course, it only lasted a day or so; no sooner did we finish it that someone dropped it and broke the case. I reached out to the manufacturer and purchased the parts I needed to fix it and quickly put it back together just in time for the cousins to visit.\nThis time, it lasted less than an hour; all these years later, I still don't know who did it, but someone wanted to see what would happen if they held the lid closed and turned on the power, so they did. You and I are smart enough to figure out without trying that if you hold the lid closed and turn on the power, it will break. Not true for kids, they had to actually try it out. Sigh.\nSo I reached out to the manufacturer to order more replacement parts - this time he felt bad for me and gave them to me for free. The parts languished in my workshop for years as I just couldn't get Lizzy to work with me to put it back together again.\nOn the Fourth of July weekend, I had a lot of free time (because we were safe and stayed home), so I worked through a lot of unfinished projects in my shop. I got things done that had been sitting there for years, including the useless machine.\nI took it apart, reassembled it, and guffawed as usual every time I turned it on (and it turned itself off). My kids are old enough that I think the experimentation period is over and I can put it out without worrying that someone's going to break it. It's now sitting in my office, right at the top of a bookshelf that sits next to the stairs down to the first floor. I thought I'd put it there for any visitors to play with, but I find that I flip that little switch every time I leave my office. Guffawing every time.\nHere's where you can buy one of the current versions of the project: https://spikenzielabs.com/Catalog/useless-machine/the-useless-machine-kit-diy-soldering-edition?cPath=1&amp;.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Discarding Data Object Edits in Ionic",
  "date":"Fri Jun 05 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1591401600,
  "url":"/posts/2020/discarding-data-object-edits-in-ionic/",
  "content":"When I first learned Ionic development a little over three years ago, the default examples for editing a data object didn't make any accommodation for the user cancelling their edit. All examples showed how to build a details or settings page which included a back button which takes the user back to the previous screen. Any edits they made to the data presented in the page were automatically saved and updated in other parts of the app that displayed the data. For some edits, especially for configuration settings, I always give my app users the ability to cancel changes.\nThe issue in doing that is that Ionic is a very capable Reactive framework, so it's designed to automatically wire the app UI to its data so any change in one place is automatically reflected elsewhere. This is a great feature, but frustrating when you don't want it to work this way.\nWhen I first encountered this, I poked and prodded at the issue for a long time before turning to Ionic Support for help. They finally helped me understand how to resolve the issue. The solution? When I open a page to edit some data, if I want to be able to discard changes, I must first clone the object then wire the page UI to the cloned object. When the user taps the cancel button, I throw away the clone. When the user taps the Done or Save button, I update the original object from the clone, then close the dialog.\nIt's a simple and elegant solution, but a solution I had a hard time finding when I needed it.\nBack with Ionic 3, the recommended solution was to use the Lodash (https://lodash.com/) clone method to make the clone, and that worked great for a while. Later versions of either Ionic or the Lodash library broke things, so I could no longer use Lodash to solve this particular problem.\nWhen this happened, I reached out again to Ionic and they provided me with a little, custom clone object I could use for my Ionic apps. Since I originally had a problem finding a solution for this, I decided I'd publish a complete sample application that demonstrated the solution. I finally got around to completing the sample yesterday and published the project (with a complete explanation of the code) to the Ionic Edit Object Sample https://github.com/johnwargo/ionic-edit-object-sample repository.\nThe app's main screen looks like the following figure. It lists a couple of simple data object properties plus options for the traditional Ionic back button edit process plus a second option where the user can make changes to the data then cancel or save their changes.\n\nI also recorded a video demonstration of the app at https://youtube.com/watch?v=nJPmmxR8_iY\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Web Development"
  
  ]
  },

  {
  "title": "Ionic Slides Example",
  "date":"Sun May 17 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1589760000,
  "url":"/posts/2020/ionic-slides-example/",
  "content":"I love the Ionic Framework, I know I've said that here before. I learned how to write Ionic Apps from Josh Morony's Building Mobile Apps with Ionic &amp; Angular book. In the book, Josh provides an example of implementing an Ionic Slides page, an interactive UI where app users swipe between a set of images (an approach you see in a lot of apps today).\nThe book's example made sense to me, but when I implemented it in my Time Slicer app I wanted to have some text at the top of each slide pages and the book didn't show me how to do that - Josh added the text to his slideshow images, but I didn't want to do that.\nAnyway, I figured out how to do it and published a complete Ionic sample app that includes a complete example of the image-only approach plus my images with text on top approach. You can find the example on GitHub.\nWhen you open the app, you see the screen shown in the following figure. Tap the first option to see an image-only example. The second has text on the pages. It's pretty straightforward and the repo includes all the source and styling to get the look I got. I'm not a huge CSS guy, so I know there's a lot more I could do to make it beautiful, I'll leave that up to you.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Platform-Specific Links in Ionic",
  "date":"Wed May 13 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1589414400,
  "url":"/posts/2020/platform-specific-links-in-ionic/",
  "content":"When I submitted the Time Slicer app to the Apple App Store, they rejected it. That was not necessarily a bad thing as I really expected them to do so. This was my first App Store submission (I will submit my second one next week) and I had no idea what I was doing, so I expected at least one rejection, possibly more.\nWhat surprised me though was Apple's reason for rejecting me:\n\nWe noticed that your app or its metadata includes irrelevant third-party platform information.\nSpecifically, your app includes non-iOS device images in the tutorial screens.\nReferencing third-party platforms in your app or its metadata is not permitted on the App Store unless there is specific interactive functionality.\n\nAaah, Yes – the app screen shots in the app's Intro and About pages. Well that was unexpected (unexpected because I never read Apple's publishing guidelines), but not a big issue to fix.\nI started thinking about how I would solve this problem, and my first thought was to use Ionic platform, or specifically Capacitor platform lifecycle hooks. For platforms that have a CLI (like Ionic and Capacitor), hooks are a way to link your code into different parts of the process the CLI manages. I came up with a different approach, one I'm describing in this post, but it turns out that the Ionic CLI has hooks (https://ionicframework.com/docs/cli/configuration#hooks) and 14 days ago someone added hooks to the Capacitor CLI (https://github.com/ionic-team/ionic-cli/pull/4417). Pretty cool stuff and something I'm going to have to look into later.\nAnyway, I decided to implement a solution that used the platform the app was running on to determine which images to load on the About and Intro pages. I'd essentially make two sets of screen shots, one for Android and the other for iOS, and load the right one dynamically at runtime. This isn't a very clean solution, since it forces the app to hold images for both platforms knowing it would only ever show one on the device. Using hooks to put the right images in the right place for Android and iOS would be the cleaner implementation, I just didn't go there.\nAnyway, so I populated the app's assets folder with the appropriate files. The images were originally called intro-01.png, intro-02.png, etc. but with the Android and iOS versions, I appended the platform name to the front of the file name, so my image files were labeled android-intro-01.png, android-intro-02.png, etc. and ios-intro-01.png, ios-intro-02.png, etc. With the files in place, I then had to update the code.\nFirst I updated the TypeScript code for each page (into.page.ts and about.page.ts) with the following:\nAdded an import for the Platform module:\n\nNext I updated the constructor to instantiate the platform variable:\n\nThen I added a variable called runningOn to the top of the page class:\n\nThis sets the default platform to Android and will cause the Android screen shots to display in the Electron or other platform versions of the app (If I ever make them)\nOn Init, we need the app to set the platform to iOS if running on iOS, so I added the following code:\n\nThis resets the runningOn variable appropriately on iOS devices.\nThis is what the Intro Page code looks like in its entirety:\n\nOn the app pages, I load the images using the ion-img component:\n\nNow that I have the runningOn variable in the app to let it know on which platform it's running; I can update the link component with the following:\n\nThis changes the URL, appending the platform name at runtime and loading the correct image depending on the platform.\nThe Ionic Platform module does not offer a method to retrieve the platform name (it should), so you must ask it for each platform. So, to add support for Electron-specific images, then the ngOnInit code would look like this:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "First App Store App",
  "date":"Tue May 12 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1589328000,
  "url":"/posts/2020/first-app-store-app/",
  "content":"My first app in the Apple App Store was accepted by Apple today and published. The app is called Time Slicer, and the Android version of the app has been available for some time now.\nI describe Time Slicer as a Stopwatch with categories; it allows users to define projects where a project is basically a collection of categories you can track time across. Here's a screen shot of the iOS version of the app listing projects.\n\nWhen you open a project, you see the list of categories and a simple stopwatch. Click the Start button to start the overall timer, the tap on any of the categories to track time for the selected category as shown in the following figure.\n\nI made the app so I could look at a block of time, like the 30 minutes for a news show, and track how much time was allocated during that time for different categories. I could be wrong, but I believe it's the perfect tool to track time allocation for activities performed by the subject of a usability test.\nAnyway, when I show app to people, the first thing they generally do is suggest additional categories or projects I can add to the app. This confuses me since that makes me think people think the app is pre-set with projects and categories. It's a mobile app, the data I show in the screenshots is sample data. Users of the app define as many (or as few) projects as they want for their particular needs and add the categories that make the most sense for the project. \nI specifically added a tutorial to the app that walks you through the process so you can see that projects and categories are dynamic - they're whatever you want them to be. But I'm trying to figure out how to make this clear to users. Any ideas?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Pandemic Lockdown Fun",
  "date":"Wed May 06 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1588809600,
  "url":"/posts/2020/pandemic-lockdown-fun/",
  "content":"I've been having a lot of fun during the Pandemic lockdown. No, I'm not being morbid about the situation, my pleasure is just a side-effect of having to stay home every day. My family's bored and irritable, but I'm having a blast. Let me explain.\nMy two favorite things to do are play Football (Soccer) and write code. I'm too old to play Soccer anymore (too many expensive and painful injuries) and I don't get many chances to write code anymore.\nI recently accepted a transfer to GitHub, and I'm now the PM for their documentation platform. We have some big plans, so I'm really having a lot of fun. GitHub is very different from Microsoft, which is expected and a good thing, but I'm really enjoying myself.\nSince I can't go out much anymore, and I'm especially not making it to the gym most mornings, I've started getting up at the same time and writing code every morning. Like I said, I'm having a blast. Let me show you the ways.\nIn the last few weeks, I've written code in: C, Dart, JavaScript, TypeScript, and Python - even some shell and batch scripts as well.\nI'm working on a book on Flutter, so I've been doing a lot of Flutter development and absolutely loving it. Flutter is everything I need for cross-platform mobile development. I'm planning on submitting my second app to the Google Play Store next week and it's a Flutter app. I'll write more about it here once it's published. \nA while back, I created a Node module that automates creating lib and asset folders in a Flutter project. The project is called Flutter Folders (https://npmjs.com/package/flutter-folders) and I made some changes this morning to enhance the module so it also updates the pubspec.yaml file to configure the assets folders the module creates.\nI created a few static sites in Jekyll, my last book's site is a Jekyll site plus my randomerrors.dev site is Jekyll too. I recently migrated my last two Apache Cordova book web sites to Jekyll sites as well, so that's a lot of Jekylling. One of the things that frustrated me about working with Jekyll is that recent updates to the framework/platform/generator configures the target system so template files are stored in Gem rather than with the site and that's caused me some problems. Whenever I need to copy one of the template files into my project (so I can modify it), I have to dig up the instructions for how to locate the template folder, navigate there, then copy the file to my project. \nTo solve this problem for me and other developers, I created a Node module called Jekyll Copy (https://npmjs.com/package/jekyll-copy). It allows you to list the template folders and easily copy them to your project folder with a couple of quick commands. No need to know where the template files are, the module reads the local config.yml file, locates the template folder and  gets to work. I know it saves me time, I hope others find it useful as well.\nI've also started a couple of hardware projects that I hope will eventually become Kickstarter projects. One's a pure hardware play while the other one has a mobile app component (along with some hardware). The mobile app's written in Flutter - that's the one I'm submitting to Google next week and hopefully Apple the following week.\nI was doing a fair bit of Arduino development - using my favorite platform: the Particle Photon. For that project, I liked the simplicity of the cloud platform, but since this application is local only, I don't need the cloud service as much. I've pivoted and I'm trying to do the same project using the ESP32. I may release the Particle version as a hobbyist project through Kickstarter but the ESP32 one will be the Pro (pre-assembled and turnkey) version. Stay tuned on that one.\nI think that covers all of my recent development efforts. I'll update you again when I have more information to share.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Flutter"
  
  ]
  },

  {
  "title": "Amazon Release of Learning Progressive Web Apps Delayed",
  "date":"Fri Mar 20 2020 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1584748800,
  "url":"/posts/2020/amazon-release-of-learning-progressive-web-apps-delayed/",
  "content":"\nSurprisingly, the Amazon release of Learning Progressive Web Apps is delayed because of the Coronavirus. Apparently Amazon told publishers they're only accepting shipments of essential items due to the Coronavirus, so it's going to be a few weeks before any Amazon pre-orders ship. \nThe good news though is that the ebook is already available on InformIT and through Safari Books Online. Print copies of the book will be in warehouse any day now, so you can purchase the print copy of the book from InformIT now and get the book in your hands in a few days. \nI presented at the Open Source 101 conference earlier this month and gave away 10 copies of the ebook. I've submitted several session abstracts for All Things Open, so I'm hoping I'll be there distributing books as well. \nI've already heard from one reader who suggested some code changes to the PWA News NodeJS application.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Open Source 101 2020 (Columbia)",
  "date":"Thu Feb 13 2020 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1581638400,
  "url":"/posts/2020/open-source-101-2020-(columbia)/",
  "content":"The fine folks at Open Source 101 selected me to present at the Columbia, SC event on March 3, 2010. I'll be presenting on Open Source tools for building Progressive Web Apps. Stop by if you're nearby.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Learning Progressive Web Apps Code Available",
  "date":"Fri Dec 20 2019 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1576886400,
  "url":"/posts/2019/learning-progressive-web-apps-code-available/",
  "content":"\nI recently published the source code repository for my upcoming Learning Progressive Web Apps (PWA) book. You can find the repository on GitHub at https://github.com/johnwargo/learning-pwa-code.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Automating Creating Flutter App Project Folders",
  "date":"Thu Dec 05 2019 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1575590400,
  "url":"/posts/2019/automating-creating-flutter-app-project-folders/",
  "content":"I've been wanting to dig into Flutter development for some time now. I've followed the project for years now and I'm convinced that Flutter is the next big thing for client software development. It feels like Flutter solves a lot of the cross-platform development issues mobile developers faced for years (and many, many commercial and open source products tried to solve, but most failed). \nWhat Flutter should solve with their Hummingbird project is also cover cross-platform development for web apps as well - enabling developers to build their native mobile app and web app with mostly the same code base. Mark my words - this is gonna be big.\nAnyway, I'm working through one of the Flutter books on the market (this one is OK, but it has a lot of issues) and one of the things I noticed is that the default Flutter project uses a simple lib folder for all your app's source code. The book suggests building a suite of subfolders there to structure your app's code and I agree. The author even suggests adding an assets folder for, well, assets, and I agree with that as well.\nExpecting that I'm going to be making a lot of Flutter apps in the future (I've already started working on my second app store project in Flutter) I decided to streamline the folder creation process with some code. Using the suggested project folder structure from the book, I created a node module called flutter-folders that implements a CLI a developer can use to create the following folder structure inside a Flutter project:\n\nassets\nassets/images\nassets/other\nlib/models\nlib/pages\nlib/services\nlib/utils\nlib/widgets\n\nYou can find the project's GitHub repository at https://github.com/johnwargo/flutter-folders, and the CLI is available from NPM at https://npmjs.com/package/flutter-folders. I hope this helps make your Flutter development a little easier.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous",
  
    "Flutter"
  
  ]
  },

  {
  "title": "Introducing the Time Slicer App",
  "date":"Tue Nov 26 2019 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1574812800,
  "url":"/posts/2019/introducing-the-time-slicer-app/",
  "content":"I was watching the evening news one day and started thinking about how much of the show was allocated to different topic categories (local news, national news, sports, etc.); I was especially curious about what the ratio was of news vs. commercials (there seemed to be a lot of car commercials). I decided to build an app that enabled me to capture (measure) the amount of time allocated across multiple categories. I thought perhaps that others would like a similar app, so I decided to publish it as my first app store app.\nI worked a bit with the Ionic framework (I published a couple of Ionic sample apps for Microsoft when I worked on the Visual Studio docs, and my Garage Controller app is an Ionic app) and I knew I wanted this app to be a cross-platform app (Android and iOS, perhaps Electron), so I decided to build this app using Ionic.\nI completed the app a few months ago, but finally got around to publishing it in the Google Play Store last week. The app's public web site is https://timeslicer.app and you can view the app in the Google Play Store using the link immediately following this paragraph. The iOS version is ready to go, so I'll submit it to Apple soon.\n\nThe way I describe the app is as a stopwatch with categories. Let me show you how it works.\nThe app uses projects to define a grouping of categories. When the app launches, you're presented with an empty project list. You can quickly create your own, or load a set of sample projects to work with. The list of sample projects is shown in the figure below.\n\nSwipe left on an item to edit or delete it. Tap the plus sign at the top of the list to add a new project. When adding or editing projects, you'll see the following screen.\n\nFrom the main screen, tap a project to open it; you'll see a screen similar to the one shown below.\n\nTap the start button or one of the categories to start the stopwatch. When you tap one of the categories, the stopwatch starts tracking time spent on that category as shown in the following figure.\n\nWhen you stop the stopwatch, you can share the results with any local application using the mobile device's standard sharing process.\nOverall, it's a pretty simple application. Figuring out how to track multiple timers simultaneously was the biggest challenge, but I eventually came up with a very elegant solution for this. I won't publish the source code for the app, but I likely will write a post here about how I solved the timer problem.\nIf you think about it, it's not a very useful app, but it does solve the problem it was designed to solve. I do think that many people will find it useful; I think its most useful for user experience and other types of researchers who watch people work or solve problems and need to track time spent on different types of activities. \nI'm certain that many users will think this is an app for tracking time (like lawyers and consultants billing their time). It can be used for that, but there are a lot of better solutions out there for that type of problem.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "9-Patch Files for Ionic Capacitor Apps",
  "date":"Tue Nov 12 2019 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1573603200,
  "url":"/posts/2019/9-patch-files-for-ionic-capacitor-apps/",
  "content":"I've been working on my first app store app; it's an app that, I think, is pretty unique. I'm submitting the app to the Android app store this week and will add the iOS version sometime before the end of the year. The application is an Ionic app and I really enjoyed writing it.\nAs I completed the app, I had one lingering bug that I just couldn't squash. I sought help on the Ionic Forums, but eventually hired Josh Morony to help me figure it out. I learned Ionic development from Josh's book and tutorials, and he was very helpful, but he wasn't able to help me squash that bug. I eventually figured it out with the help of Mike Hartington from the Ionic team figured it out. Thanks Mike!\nWith the bug squashed, it was time to start thinking of putting the finishing touches on the app's UI, and that meant adding a splash screen to the app. I hired rupindersingh on Fiverr to design an icon and splash screen for me but on the Android app the splash screen just didn't look right. Android uses 9-patch files to create a dynamically expandable splash screen image but I just couldn't figure out how to make one (the docs for the 9-patch tools in Android Studio are light, very light). I reached out to Josh Morony and asked for more help. He said that he'd been wanting to figure out how to work with splash screens on Ionic Capacitor and offered to figure it out and publish a blog post about it; you can find the resulting blog post here.\nWell, Josh's article got me to where I needed to be – the splash screen works perfect on Android/Capacitor now. However, I really struggled with Josh's 9-patch instructions – with his help, I was able to figure it out, but it just wasn't easy. With that in mind, I took Josh's article and updated it with my learnings and sent it to him so he could update his article with the additional information I learned. In response, he said “Thanks for taking the time to share your experience, I'll review your edits and incorporate them in a new version of the article when I have some time.”\nIt's been four months and I haven't seen an updated to Josh's article yet, so I decided to go ahead and publish mine. I really appreciate Josh's help and the article he published clearly helped me get over the hump and got my splash screen working. I just think developers need more information about how to create 9-patch files. With that in mind, here's my version of the 9-patch article with Credit to Josh for his help.\nThe 9-Patch File\nA 9-Patch file is a special type of image that has an extra 1px border all the way around the original image. Within this 1px border, you set individual pixels either black or transparent to instruct how the image should be stretched by the device at runtime. When the Android OS renders the image, it deletes (or hides, who knows) those black pixels and stretches that image area as needed to properly display the image on the screen.\nFor example, in the following figure you can see how the highlighted areas have black pixels set, indicating that those are the parts of the image that stretch to accommodate the device's screen resolution. By marking sections on the top and left border with black pixels, we can indicate the sections that we want to be stretched to fit the required screen dimensions (these sections are shown in pink).\n\nAll you need to a create a 9-patch file is an application that can add that 1-pixel border to the image file and let you set, or clear, pixels in that border to create the stretched image you need. I looked around and didn't find any image editors that supported 9-patch files out of the box, but here are some articles that show how to do it in PhotoShop. The good news is that Android Studio can create the files for you automatically (but instructions for how to do so are fairly useless).\nYou can also add black pixels on the right and bottom border, but this does not define the area to be stretched. This defines the area to be “filled”, which is not required in our case for splash screens.\nCreating 9-Patch Files\nAt this point, follow Josh's instructions for creating the necessary image files and configuring the Android project. Back in Android Studio, right-click on each of the new splash screen files and choose Create 9-Patch File.... When prompted, save these new files in the same folder as the original splash screen and keep the splash.9.png name Android Studio uses by default.\nOnce you complete the adjustments to the new 9-Patch files (covered in the next section), you can delete the original splash screen files. If you leave them there, you'll get an error during build, so you do have to delete them, but not now. Android Studio has a nasty quirk that will cause you pain if you delete the original files now. Whenever you make a change to the file using Android Studio's 9-patch editor, the changes are immediately written to the file and there's no undo. So, in the next section when you're making changes, if you mess it up, you'll have to delete the 9-patch ",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Learning Progressive Web Apps Cover",
  "date":"Wed Aug 21 2019 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1566432000,
  "url":"/posts/2019/learning-progressive-web-apps-cover/",
  "content":"I received the cover for Learning Progressive Web Apps today, what do you think?\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Time for a New Book",
  "date":"Mon Jun 03 2019 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1559606400,
  "url":"/posts/2019/time-for-a-new-book/",
  "content":"I've been really interested in Progressive Web Apps for the last couple of years, and I finally convinced my publisher it was time for a new book on the topic. The book is called Learning Progressive Web Apps and it will be available around Christmas time.\nIf you've read any of my Apache Cordova books, you'll know that Adobe PhoneGap and Apache Cordova were created to address a gap in mobile development capabilities. The project team went out on a limb early saying that they're plan was to make Apache Cordova obsolete - well, it's progressive web apps that does this. \nPWAs give web developers tools they can use to build web apps that act and feel more like mobile apps. Supporting things like background sync, offline mode, installation, and push notifications. PWAs are so popular that Gartner says that 50% of consumer-facing apps will be PWAs in 2020 (next year as I write this). With all the advanced capabilities added to the browser over the years plus the stuff PWAs add, native mobile apps will be the exception, not the rule going forward.\nI'll fill in as I work to complete the book; I expect I'll have the manuscript done by the end of September.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Building My First App Store App",
  "date":"Tue May 21 2019 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1558483200,
  "url":"/posts/2019/building-my-first-app-store-app/",
  "content":"For the last few months, I've been working on my first app in smartphone app stores. I had an idea in my head for a few years now, and I finally got around to building the app. I'm fascinated by Ionic, and learning Ionic 4 got me started with this app.\nThe app's feature complete (although there's one small issue with the splashscreen), so I'm working on the company and app web sites before publishing the app to the stores.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Updated My Pi Remind Project (December, 2018)",
  "date":"Sat Jan 12 2019 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1547337600,
  "url":"/posts/2019/updated-my-pi-remind-project-(december-2018)/",
  "content":"I've been running my Pi Remind project at my desk now for several years. I started with the Pi Remind (https://github.com/johnwargo/pi-remind), but then upgraded the hardware to the higher resolution Pi Remind HD (https://github.com/johnwargo/pi-remind-hd) hardware. The project essentially gives me a visual reminder when I have an upcoming appointment on my personal calendar. My personal calendar is online using Google Calendar, so it's easy for the Raspberry Pi to connect to my calendar through Google's public API.\nWhen I created my original project, my employer at the time used the G-Suite for corporate email, calendar, etc., so I was able to get all of my work calendar reminders on it - that's ultimately why I created the project.  I work at Microsoft now and, while I can connect to Office 365 from the Raspberry Pi, I didn't want to take the risk as It would require me messing with the corporate directory. Perhaps some day I'll get around to updating the project for my work calendar; we'll see.\nAnyway, I'd been having a problem with power in my home office, for some reason we get a lot of outages (really quick off, then on - frying several PC power supplies in the process), and my Pi Remind Raspberry Pi would restart, but not get connected to the network before my cable modem completed its restart. This left the Pi in a state where it was up and running, but it couldn't see anything on the network. This needed fixed.\nI have two options to fix this problem:\n\nConfigure the Pi to wait for the network before booting (described at https://raspberrypi.org/blog/latest-raspbian-update/)\nModify my project's code so it detects that it's not been able to connect to the network for a number of minutes (defaults to 10), then reboots the Pi so it can reconnect.\n\nI chose not to use the first option since I didn't want the Pi sitting there in limbo if my network didn't come up in a reasonable time. The project displays a red warning light (LED) when it can't see the network, so it was better for me if it booted, then notified me via the HAT's LEDs that it couldn't connect to the network.\nSo, the code up on GitHub has the reboot after # minutes (defaults to 10, you can easily change it in the source code). It's disabled by default, so you'll have to enable it (pretty easy to see how in the code) before you can see it in action.\nI should put the configuration settings in an external file, enabling you to update your code when I make changes and not lose your settings. Perhaps that will be my next update to this project.\nI periodically get emails from users asking me questions about the code or to fix some problem they've found. Surprisingly, so many of them start by assuming I'm not going to respond (starting their emails with something like “I know you probably don't have time to respond…”). I published the code so others could use it, and I'm happy to answer questions or fix problems with the code. Either create a GitHub issue (the preferred way) or send me an email from the contact area of the site. You can even send me an email directly, my email address is my first name at, well, you know, my whole name (the site you're on).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "What Happened to Commas in Numbers",
  "date":"Mon Dec 10 2018 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1544486400,
  "url":"/posts/2018/what-happened-to-commas-in-numbers/",
  "content":"That's pretty much it, what ever happened to them? Nobody seems to use them anymore in software products. I've noticed this at work where people make dashboards showing big numbers, but don't show thousands separators when displaying them on a page or in a screen.\nTake, for example, the Stupid Developers Tricks section of this site (shown in the following figure). Several of the articles in this category have more than a thousand hits, but whomever wrote the Hits counter plugin didn't consider rendering the separators that make reading the numbers easier.\n\nWhy is this happening? Are developers just lazy? Are there just not functions or libraries available that return a string representing the number with the right separators based on locale?  It makes no sense to me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "NC Lottery App",
  "date":"Mon Dec 10 2018 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1544486400,
  "url":"/posts/2018/nc-lottery-app/",
  "content":"Don't tell anybody, but I buy lottery tickets; my wife says it's the only illogical thing about me, and she's probably right. I know in my heart that my chances of winning are only slightly higher when I play, but to retire early? Worth the few dollars per week.\nI live in North Carolina (US), and the NC Education Lottery (yep, lotteries are all about the education, aren't they?) has a mobile app I can use to check my numbers. The problem is that the mobile app is so poorly designed that it's almost impossible to use for its intended purpose.\nLet me show you the ways…\nThe app has a feature which allows me to check to see if my ticket is a winner. Unfortunately, the NC Lottery created two major issues that affect my ability to actually do that. For some bizarre reason, NC lottery tickets have two barcodes on them. One is for their Lucke Rewards Program (their typo in the name, not mine), and the other is so the vendor (and the app) can check to see if the ticket is a winner.\n\nNote: I imagine the reason there are two barcodes on the ticket is because North Carolina is the only state that has the poorly named Lucke Rewards program, so there's no way for them to use the same barcode for both. Unfortunately, the barcode scanner on your phone (its camera) you'll use to check to see if your ticket is a winner can't read the barcode when there's two barcodes on the ticket. You can scan the top barcode (toward the middle of the ticket) to collect your rewards, but when you try to check to see if you're a winner, the scanner fails most every time.\nTo get around this, you have to cover the upper barcode with a piece of paper or cardboard before attempting a scan. How stupid is that?\nNotice the SCAN NOW button in the figure. It's a smartphone app screen, right? Notice how the button's too small to tap with your finger? The same is true for the collecting rewards section of the app as shown in the following figure. Poor design, not paying attention at all that users will be doing this on a smartphone.\n\nThe second major issue with the app is that the designer, or the development team that crafted the app didn't seem to consider the use case where a user needs to check more than one ticket at a time. They seemed to just assume you'd check a ticket every draw day, rather than collect them, and check them all at once.\nIf you look at the results image below, you can see that the last ticket I checked was not a winner. Bummer, right? From a design standpoint, what's wrong here? Well, why do I need two buttons on the screen that both do the same thing?\n\nAlso, notice that the top button is finger-friendly. If the designer noticed that this button needed to be bigger so it can be easily tapped by a finger, why wasn't the same approach taken with the original button (which is still displayed)?\nMy real issue here though is that whomever coded this, doesn't clear the results area of the page when scanning another ticket. So, if I scan a losing ticket, then scan another losing ticket, there's no visual indicator that I've scanned a new ticket. The page doesn't clear or refresh, NOTHING changes on the results page between scans. Useless, absolutely useless.\nIf the ticket is a winner, confetti falls from the top of the screen and the results panel updates with the prize, so it's easy to see that the scan works. When scanning two losing tickets in sequence, there's no way for me to tell whether the app just failed scanning the second ticket. Designers and developers:\n\nThink through all use cases.\nWatch real users actually use your app\nAsk questions of people who don't already know how to use your app\n\nThe most interesting things I've learned from users is how they use tools in different ways than the tool (app) designer expected. That's one of the most interesting aspects of using Analytics tools to track how users use your app - you can sit in your office or cubicle and 'see' the path people take through your app. With that data in hand, make decisions on where to invest your efforts, or how to update your app designs to better accommodate your user's needs.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Apache Cordova 3 Programming Site Retired",
  "date":"Sun Jul 01 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1530489600,
  "url":"/posts/2018/apache-cordova-3-programming-site-retired/",
  "content":"\nI shutdown the web site for my Apache Cordova 3 Programming book today. The book came out in 2013, and was replaced a year or so by my Apache Cordova 4 Programming book. Cordova's at version 8 right now, so there seems to be little need for a website about a book for Apache Cordova 3.\nYou can still buy the book, but there's no longer the need for a promotional website. Don't worry, the code from the book is still up on GitHub.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Protecting Data in a URL",
  "date":"Sat Jun 30 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1530403200,
  "url":"/posts/2018/protecting-data-in-a-url/",
  "content":"A while back, I created a remote garage door opener project using the Particle platform.\nThe Particle Platform (devices and cloud services) enables developers to write code running on an Arduino-compatible device that can be remotely executed via a cloud service. Connect a Photon and a relay to a garage opener and you have the gist of my project.\nOne of the cool features of the project's mobile app is that it enables app users to generate a single-use key, deploy it to the garage door opener, then send a URL to someone who requires access to the garage. The feature is something I hacked together and it works pretty well (I've been using it in my house for years). The system only supports one single-use code at a time, but when you need to get someone into your house when you're not around, it works great.\nI've been working on an update to the project, and one of the things I wanted to do is protect the homeowner's private information in the URL sent to others. In order to use the Particle platform from an application, you must have the Particle user's Access Token plus the device ID for the Particle Photon attached to the garage door opener. For the single-use code scenario, you also need the single-use code.\nFor my project, I basically built a web application that has the user's configuration hard-coded in the app's configuration. The mobile app that generates the single-use code merely builds a URL pointing to a hosted web app and passes in the single-use code on the URL. The hosted web app pulls the access token and device ID from it's local config file, and it's all ready to go. The problem with this approach is that it requires the user to modify a web app and host it somewhere in order to deploy the project. Now, there are a few places where you can host a web application for free, but it's still too complicated for many users to configure, setup and deploy the web app. I needed a better way.\nI decided to build my own hosted web page to use for the garage opener project, I'd remove the configuration from the web application code and just include the three required configuration settings in the URL generated by my project's mobile app.\nAs I started thinking through the implementation of this approach, I quickly realized that I didn't want to pass the Access Token, Device ID, and Single-Use code in clear text in the generated URL. Nope, I needed a way to encrypt those values in the URL. Otherwise, anyone snooping traffic could grab those values and hack their way into the garage. Granted it's not a high risk that someone will be snooping your garage door opener traffic, but I'd rather be safe than sorry, and this gave me an interesting computing problem to solve (my favorite).\nI'm not a native mobile developer, so the mobile app I'd deliver would be an Apache Cordova, Ionic, or React Native app. I knew there were encryption libraries for JavaScript, and I set about finding the best one to use for my project. I realized through that encrypting the data in an app wasn't safe, a knowledgeable user could tear apart my code and hack the system. The encryption key, and encryption algorithm would be in the code, so that's not even close to being secure. That wouldn't work.\nI poked and prodded at several potential solutions, but none panned out. I wanted (needed) this architecture to be both simple and secure, and nothing good came to mind. I started asking a colleague about possible options for encrypting the data using JavaScript and he quickly suggested using a serverless function to encrypt the data.\nI tried to quickly discount this approach because I didn't want to pay for compute in the cloud, but then he reminded me that I could use Azure Functions for free (Microsoft offers Azure Functions in a free tier for a ridiculous number of function calls per month [more than I think I'll ever use for this project]).\nTo prove the validity of this solution, I logged into my personal Azure account, created an Azure App Service Functions instance and got to work. Before long I had it working; it was quick, simple, and a rather elegant solution to my problem. The purpose of this article is to show you how I did it in order to help others who may have this same problem.\nFor my implementation, I created two services:\n\nsetSingleUseCode\npushButtonWithCode\n\nThe setSingleUseCode function:\n\nGets the Particle Access Token and Device ID in the body of an HTTP request.\nGenerates a single use code\nCalls my project's Particle API to register the single-use code with the selected device (by the Device ID passed to the function)\nOnce the function knows that the single-use code was successfully registered with the Photon device, it:\n\nCreates a JSON object containing Access Token, Device ID, and Single-use code.\nEncrypts the JSON object using my super special, secret encrypting key.\nBuilds a URL for my hosted web application, appending the encrypted data as a parameter in the URL.\nReturns the URL to the calling application.\n\n\n\nThe c",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Particle Photon and the National Control Devices Relay Board",
  "date":"Sat Jun 30 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1530403200,
  "url":"/posts/2018/particle-photon-and-the-national-control-devices-relay-board/",
  "content":"If you've read my most recent stuff in Make Magazine (4 Ways to Control Electronic Relays), you know I like working with relays. One of the projects I showed in that article is a garage door opener project I built using a Particle Photon and a relay controller from a company called Control Everything. I needed to build a couple of these devices for some family and friends, but my original relay board is no longer available. Control Everything is now National Control Devices, and the small and simple Photon Relay board is now the 1-Channel 1-Amp SPDT Signal Relay Board + 7 GPIO with IoT Interface.\nJust in case you're interested, here's the specs (from the NCD website) on the new board:\n\n1-Channel Relay Controller with IoT Interface\n7-Channel Programmable Digital Input/Output (GPIO)\nCompatible with Electron, Photon, Bluz, or RedBear\nAdaptable to Onion, PyCom, Raspberry Pi, Arduino\nMCP23008 I2C Controlled Mechanical DPDT Relay\nChoose 1, 3, or 5-Amp DPDT Signal Switching Relays\nWorld's Most Expandable Controller with I2C Expansion Port\nWireless Remote Operation with Key Fob Expansion Option\nESP8266 and USB IoT Interface Modules are Also Available\nIFTTT Firmware Available for Internet Relay Control\nExample Libraries Available on GitHub\n\nMissing Documentation\nAs you can see, one of the features of this board is the GPIO ports it exposes along with a relay, they give me the ability to control some LEDs along with switching the relay. You can also use those GPIO ports as inputs, but for my project, I wanted to use them as outputs (driving two LEDs).\nAs I started assembling my hardware, I noticed that a lot of information you need to interact with the relay board is missing from the product's sparse documentation. Specifically, there was no information available on how to use the GPIO functionality on that board.\nI let the folks at NCD know, and asked them to update the docs, but what I heard back was “Honestly I wrote these libraries a long time ago and that functionality just wasn't something I thought of at the time. We release these libraries to the public for free so we really don't make a whole lot for developing them which limits the amount of time we as a business can invest in updating them for feature additions.”  \nSo, basically, they're saying it's not worth their effort to update the docs so you'll know how use their products. Nice!\nI fixed some typos in their docs and submitted pull requests, but so far they've not accepted them or even responded to let me know that they won't use them. Sigh.\nWith that in mind, I thought I'd fill in some of the blanks in the docs so if you buy one of these boards, you'll actually be able to use it to its full extent in your project.\nMounting the Photon\nThe original relay board only supported the Photon, so it was easy to mount the photon to the relay board. The board came with markings indicating which end of the photon went where.\nThe NCD documentation doesn't include any instructions for how to connect the Photon to the relay board, nor are there any product pictures using the Photon. The new relay boards accommodate a wider variety of microcontrollers (adding the Electron, Bluz, or RedBear) which have more pins (connectors) than the Photon, so the relay board has more sockets than the Photon has pins.\nSo, if you look at this image (which shows a microcontroller I don't recognize), it's using all the sockets. The photon aligns with the far right of the board (as shown in the figure) with the Photon's power connector pointing off the end of the board. When you mount the board, make sure the first pins on the board insert in the sockets at the edge of the board. When you're done, there will be a bunch of sockets open to the left of the Photon.\nNormally I'd simply take a picture of my hardware, but I've already completed assembly of my project and I'd have to take it apart to grab a photo. I had a reason to take the project apart, so here's a photo that shows how the Photon fits on the relay board.\n\nUsing the GPIO Ports\nNow, here's where it gets funny. NCD calls the single relay board the NCD1, the 4-relay board is the NCD4, and the 8-relay board is the, wait for it…, the NCD8. The software library for the NCD1 exposes a single set of methods for interacting with the relay: turnOnRelay, turnOffRelay, and toggleRelay. Since the relay board only has 1 relay, those methods don't even require a parameter to indicate which relay you're turning on/off or toggling. You simply call the method and it does what you want with the single relay on the board.\nRemember the 7 GPIO channels?  Well, the library only exposes methods you can use to read values from the GPIO channels used as inputs.  You Photon firmware can call readInputStatus and pass it the number (1-7) of the GPIO port you want to read, and it will return a value indicating the value read from the port. Your project's firmware can also call readAllInputs which returns the status of all of the GPIO ports represented as bi",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Microsoft Announces Plans to Acquire GitHub",
  "date":"Wed Jun 27 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1530144000,
  "url":"/posts/2018/microsoft-announces-plans-to-acquire-github/",
  "content":"A few weeks ago, Microsoft announced its intention to acquire GitHub, and I don't understand what the fuss is all about.\nNote: I work for Microsoft, but this post is NOT official communication from Microsoft. Its merely my personal insights on a topic that I find interesting. I am not authorize to speak on Microsoft's behalf on this topic, so do not construe anything you read here as an official statement by my employer.\nGitHub is a great platform for sharing code. I use it extensively for personal coding projects, work related stuff (most of Microsoft's docs are published through GitHub), and my past work with the open source Apache Cordova project.\nLooking at the different articles and posts on the Internet, it's clear that there are two camps out there; one that things Microsoft owning GitHub is a good thing, and the other that thinks it's the worst, possible, thing, ever!\nThe first group is right, Microsoft buying GitHub is a good thing. Those foretelling the demise of GitHub at Microsoft's hands are wrong, and are so busy looking far into the past that they can't see the open world they live in.\nYes, Microsoft's Steve Ballmer did say that Open Source was a cancer. We all heard that (and most of us cringed when we saw or read it). We all, I hope, know that Ballmer was wrong, absolutely wrong. At the time he said that, the software business was a commercially licensed software world. There were open source companies, but enterprises and consumers still bought licenses for their most important apps (the ones they use the most, or the ones they ran their businesses on). We don't live in that world anymore, and we haven't for a while now.\nOpen Source won!\nSoftware companies (like Microsoft) still exist, but the most large companies run their more modern software on open source stacks. Software companies adapted and switched to a pay per use approach (cloud services, SaaS, and PaaS) or they offer additional capabilities or support for open source solutions. There's still a lot of for fee apps out there, but the world has switched to open source for so much software nowadays that it's hard to imagine paying big dollars for software like we did in the past.\nMicrosoft has fully embraced open source. They're the biggest publisher of open source software on GitHub. Visual Studio Code, a free, open source developer editor from Microsoft is the most popular editor used by developers worldwide. Don't forget the Monaco editor (https://github.com/Microsoft/monaco-editor the editor at the core of Visual Studio Code is open source and available for anyone to use any way they want to.\nThose naysayers who are freaking out about our pending purchase (Microsoft hasn't purchased GitHub yet), do they realize that Monaco is likely used in many products that compete with Microsoft products and Microsoft doesn't care?\nBack to the timing of the acquisition, Microsoft was very clear that it's trying to close the deal by the end of the year. What that means is that Microsoft doesn't own GitHub. Microsoft signed a letter of intent to purchase the company, and the two companies are going to work diligently over the next 6 months or so to make that happen, but NOTHING HAPPENS at GitHub until the deal closes. Nat Friedman will be CEO of GitHub, but he isn't now, and he legally can't direct GitHub employees to do anything.\nTo all those backward looking developers who publicly announced the closure of their GitHub accounts, why? GitHub is the exact same company it was on the Monday before the Microsoft announcement; exactly the same. Why the rush to close your account? In a fit of pique, you're going to abandon the tool you use to manage the source code for all of your projects just because of something you think may happen in six months or so?\nI know Microsoft will fulfill its commitment to leave GitHub alone, why not wait to see that proven? I know Nat Friedman will work very hard to earn the community's trust, why not stick around to see that?  Did the world end Monday? Nope. Will the world end when this deal closes? Not likely. Calm down, take a breath, and watch what happens before you make a decision.\nIf Microsoft closes the deal, makes some changes at GitHub, and you don't like the changes, feel free to move on. But until then, listen to people who really know Microsoft and know how the company feels about Open Source. Open source isn't a cancer, it's the backbone of the technology world and something Microsoft fully supports.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "SiteLock's Deceptive Sales Tactics",
  "date":"Mon Jun 18 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1529366400,
  "url":"/posts/2018/sitelock-deceptive-sales-tactics/",
  "content":"I'm a SiteLock customer; my hosting provider offers the service at a discount, so I signed up for it on several of the sites I manage. My ISP uses SiteLock to scan customer accounts for malware, and, of course, SiteLock tries to upsell me on more rigorous scanning.\nA few weeks ago, I received an unsolicited email from Justin McCulloch, a SiteLock Security Consultant, informing me that they'd detected a problem with the site. Here's what he said in the email:\n“My name is Justin and we are partnered with Fatcow, we do all of the web security for your website. We were notified that you have some serious issues that are present which can harm your website. We want to go ahead and get these issues addressed as soon as possible. Please reach me at my contact information below.”\nHere's the email:\n\nIf they're partnered with FatCow, how is it that he doesn't know that FatCow spells its name with a capital C?\nHoly crikey - “serious issues”? That sounded ominous, I'd better look into this.\nRecognizing that the email message didn't contain any information I could use to understand which of my accounts was affected by these “serious issues”, and what those “serious issues” were, I quickly sent off a reply email asking for more details. Rather than respond to my email, he called my home office number 4 out of 5 business days every week for two weeks. In one of his messages, he finally indicated which account(s) had the &quot;serious issues&quot;.\nI know that my ISP periodically scans for malware, and creates a text file in a folder on my account's server listing all of the issues it discovered during the scan. I quickly fired up my trusty FTP client, navigated to my server, and looked for the file in the file system. Nope, nothing there.\nBoth sites he mentioned are WordPress sites, and I know that I have malware tools running on both of them, I logged into the WordPress admin for each site and checked scan results for both. Nothing there either.\nI finally made it home for a couple of days and called Justin McCulloch at SiteLock. He wasn't in, so I left a voicemail message for him and he quickly called back. When I asked him about the “serious issues” on my accounts, he began explaining to me how SiteLock worked. I interrupted him and told him that as a professional software developer and a SiteLock customer, I knew how they work and what they do.\nHe then started explaining to me that the scanner that FatCow offers only scans a certain number of pages of a site, and since my site was 'larger' than the number of pages they were scanning, many of my pages were not being scanned.\nThis is the “serious issues” he's been pestering me about?\nI've already told you that the sites in question, the ones with “serious issues” are WordPress sites. I know their scanner scans the WordPress files looking for malware, so it doesn't matter how many 'pages' my site has, if they've scanned the code, they've scanned most everything. Everything else is just data in a database.\nOne of the sites with “serious issues” is a simple blog accessed by just a few people. I'm the only one who has admin access to the site, and I haven't updated the site in a really long time, I knew that it didn't matter how many pages I had, the full site had been scanned by SiteLock.\nThe other site with “serious issues” is a site I just created for a local fundraiser. I'd done nothing except install WordPress, so the site has no pages, no posts, no plugins, nothing. No risk there either.\nSo, all this stress and concern over the “serious issues” with the site was nothing more than an opportunity for Justin McCulloch at SiteLock to try to sell me additional services.\nI explained to Justin McCulloch from SiteLock that I was a technical guy who understood the risk, and that I didn't need additional services from SiteLock. He continued to press, even trying to tell me that if I didn't address these “serious issues” now, it would be much more expensive to fix them later. There were no “serious issues” my sites don't have any malware. As I tried to explain this to him (probably rather impolitely) he reacted by hanging up on me.\nI quickly looked up the main phone number for SiteLock and gave them a call. I was able to connect with a customer service manager and tell my story. Obviously this isn't SiteLock's normal operating procedure, I assume there are many SiteLock employees who wouldn't consider lying to customers in order to get more business from them, I just happened to get one who didn't mind lying about “serious issues” with my site in order to scare me into buying more services.\nI'm considering cancelling my SiteLock services. This experience didn't help, but I also had a very long period where my primary site (this one) was regularly hacked and SiteLock wasn't able to do anything about it. SiteLock has a product I could buy that probably would have blocked many of the hacks I experienced, but as a lone developer writing about his projects, I can't afford the $600 or ",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Super Short Tutorials Failure",
  "date":"Mon May 07 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1525737600,
  "url":"/posts/2018/super-short-tutorials-failure/",
  "content":"I subscribe to several of the few remaining technical magazines in the technology and Maker spaces.  I've noticed recently that these magazines publish really, really short tutorials. I imagine they do this in order to deliver more articles in a single publication, but the end result is that these tutorials are relatively useless from a learning standpoint.\nNow, don't get me wrong, there are a lot of tutorials in these magazines.\nMy issue is that, for many of them, they set an arbitrary length limitation (usually 2 or 4 pages) for the article, no matter how complicated the topic. When this happens, the writer has to deliberately omit a lot of details about what's going on with the project.\nI've found that these short articles have the following issues:\n\nAbrupt introduction - for many of the articles, the author skips completely describing what it is you're building. If you're several paragraphs into a tutorial and you don't yet know exactly what you're learning, is it your fault, or the author's?\nCommands without reason - so many times you'll be working through a Linux tutorial and you'll be instructed to execute certain terminal commands without any explanation of why you're executing these commands. Without any information about why you're doing certain steps, how exactly are you learning?\nMissing troubleshooting information - great, the author's told you what command to execute and is already off describing the next step. What if the command doesn't work? What if the output you see is different than what the author tells you you should see? How exactly are you going to be able to complete the project? With every step should come a simple but useful description of what could go wrong. If it works, the reader can quickly skip ahead to the next step. If it doesn't work, the reader has what he or she needs to recover from encountered errors.\nForced images - One magazine I've written for demanded a specific number of images for every page of content. I get it, eye candy makes the articles more pleasant to look at, and breaks up the text. What happens if you're describing something that doesn't have images (like programming or language concepts)? This causes many authors to make something up, create images just so you'll have them to look at. The best example of this for me is Raspberry Pi tutorials where authors include screenshots of terminal windows - which are completely illegible on the printed page. Publisher requirement met, but user value not met.\nIf the author's any good at organizing his or her thoughts and writing, and you're any good at following instructions, then chances are you'll finish the process with a discernible result. However, will you have actually learned anything?  The instructions work for the specific hardware and/or software setup, but will you be able to apply what you did to other scenarios? I doubt it.\n\nThese authors are working for very little, or no money, but are trying to share their knowledge and experience. I love that! That's one reason why open source software is so spectacular. We need to be vocal about our wishes here. Let us learn as much as possible from these author's great work. Demand that these magazines relinquish control and let the writers write complete tutorials. During the editing process, trim out the extra and unneeded stuff, but let the complete description of the process be free!\nPhoto by Charisse Kenion on Unsplash\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Pug and JavaScript Functions",
  "date":"Fri May 04 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1525478400,
  "url":"/posts/2018/pug-and-javascript-functions/",
  "content":"I'm building a node-based web application using Express and Pug. As part of this project, I wanted a page that triggered some business logic using data I passed to the page (a Pug view) when the user taps a button on the page. My button code looks like this:\n\nWhen I access the page, the code for the onClick event looks just like the code in the snippet above:\n\nWhich, of course, won't work. Pug wasn't processing the variables at all as long as they were in the onclick quoted string. I poked and prodded at the Internet for a while and couldn't find the solution anywhere. No matter what I did, the variables didn't expand correctly.\nAfter a while, I finally came up with the solution. It's not pretty, but it works; here it is:\n\nInstead of trying to expand the variables in the onclick event, I created a separate function on the page and there the variable values expand correctly. Again, ugly code, but it works.\nI'm publishing this here just in case I can help anyone else with the same problem.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "JavaScript",
  
    "Web Development"
  
  ]
  },

  {
  "title": "Building a Better Light Timer",
  "date":"Fri Mar 23 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1521849600,
  "url":"/posts/2018/building-a-better-light-timer/",
  "content":"Make Magazine recently published an article of mine entitled Relays 4 Ways (they called it4 Ways to Control Electronic Relays, but I like my title better), you can find the article here: https://makezine.com/2018/03/19/control-electronic-relays This article was intended to accompany the Relays 4 Ways article as an example of a complete project using one of the components described in the article. For whatever reason, the folks at Make didn't want this one, so I get to publish it here. Enjoy!\nIntroduction\nIf you're a homeowner like me, you probably setup one or more light timers in your house whenever you leave for vacation. These devices are great, they turn any connected device (usually a light fixture) on and off on an adjustable schedule. Many devices let you set two on/off time pairs (one in the morning and another at night for example) while more sophisticated (read expensive) devices let you set as many as you want.\nThe problem with these timers is that you must manually set the on/off times, plus you must ensure the device clock is set to the proper time every time you plug them in. If you're out of town and the power goes off for any reason, when the power comes back on, the time will be off, and suddenly this inexpensive home security device turns your lights on and off at unexpected times instead of when you want it to, almost broadcasting to potential burglars that you're not home.\nTo help get around these limitations, its time for a better light timer. With this project, you'll build a microcontroller-driven light timer that sets its own internal clock automatically via the Internet and turns the light on and off on an exact schedule. The project uses a Wi-Fi enabled Arduino device, and uses the device's Wi-Fi connection to query an Internet time server for the current time. I used a real-time clock (RTC) module to store the time between sessions just in case the device can't connect to the Internet to determine the current time on startup. Figure 1 shows the completed project.\n\nFigure 1: The Better Light Timer\nWhat's missing from the photo is power for the microcontroller; for this project I used a simple smartphone charger. To run this project, you'll need two available power outlets, one for the light fixture, and the other to power the light timer.\nWithin the project's code, you'll define an array of on/off times that controls when the lights go on and off. I also added a push button to the project so you can turn the lights on/off manually as needed.\nNote: Switching AC Power (110V in the US or 220V elsewhere) is dangerous; if you don't do it right, you can harm yourself or even start a fire. To eliminate most of the risk in working with high voltages, this project uses a power pigtail to manage the power control aspect of the project. You'll learn more about this component later.\nComponents\nFor this project, I used the following components:\n\nAdafruit Feather M0 WiFi - ATSAMD21 + ATWINC1500 (https://adafruit.com/product/3010).\nAdalogger FeatherWing - RTC + SD Add-on (https://adafruit.com/product/2922).\nFeather Header Kit - 12-pin and 16-pin Female Header Set (https://adafruit.com/product/2886).\nFeather Stacking Headers - 12-pin and 16-pin female headers (https://adafruit.com/product/2830).\nPowerswitch Tail II (https://adafruit.com/product/268).\nSPST momentary push button (https://amazon.com/gp/product/B00OJZPMD2).\n5V 2.4A Switching Power Supply with 20AWG Micro USB Cable (https://adafruit.com/product/1995).\nProject enclosure – For my project, I used the Hammond 1591M, a 3.3” X 2.2” X 0.8” enclosure (https://amazon.com/gp/product/B00HKIQG3U).\nAn approximately 6 x 6 X ¾ piece of plywood, painted black (or your color of choice).\n4 #8 x ¾ wood screws (or equivalent).\nA few lengths of 20 or 22 gauge wire: black, red and some other color of your choice (I used blue).\n\nAbout the Powerswitch Tail\nThe Powerswitch Tail (PT) is basically a box containing a relay with its switched connection wired across one of the conductors in an AC power plug. When you apply a specific voltage (normally between 3V and 5V) to the input connections on the PT (shown with two red wires connected to it in the figure) the relay triggers and AC current passes through the power cord. The PT is normally wired for normally open (NO) operation, but you can usually reconfigure the PT for NC operation as well.\nNote: Refer to my article Relays 4 Ways for more information about relays.\nFor this project, I used an Arduino-compatible microcontroller to apply that voltage (under program control, of course) to the PT input triggering the relay inside. When the microcontroller sends a voltage to the PT, its relay closes and AC power flows through, powering whatever is connected to it. When the microcontroller removes the voltage, the relay opens and power stops flowing through the PT.\nNote: For this project, must provide two power sources, one to power the microcontroller (a smartphone charger providing 5V DC) and another to power the e",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino"
  
  ]
  },

  {
  "title": "Advancing Technology in Wilmington Meetup",
  "date":"Thu Mar 15 2018 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1521158400,
  "url":"/posts/2018/advancing-technology-in-wilmington-meetup/",
  "content":"I had an opportunity this week to present at the Advancing Technology in Wilmington Meetup in Wilmington, NC. The sponsors of this organization found the video of my presentation from the ReactiveConf 2017 and asked if I'd like to speak to their group. I, of course, said yes.\nThe session I delivered covered how to implement A/B testing in a React Native application using Visual Studio App Center. Here's a link to the session.\nSince the ReactiveConf session, Visual Studio App Center hit General Availability (GA) and the SDK I used for my session upgraded from the preview Mobile Center SDK to the production grade App Center SDK. I decided I'd upgrade the app and presentation for the latest version of App Center and repeat the session from last year. Since last year's presentation, App Center's received some new features, so I was able to show off a little more of the product. Also, I had as much time as I wanted for my session (instead of only 30 minutes at ReactiveConf) so I was able to slow down and cover everything a little more thoroughly.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Editing Content in Screenshots",
  "date":"Sun Feb 18 2018 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1518998400,
  "url":"/posts/2018/editing-content-in-screenshots/",
  "content":"I take a lot of screenshots for my books, magazine articles, blog posts and product documentation. I've gotten pretty good at it, not because I have any special skills, instead its all about the tools I use.\nI use TechSmith's Snagit tool on Windows and macOS; I've had licenses for this product for more years than I can count. Originally just for grabbing whole screen or window captures, the product's matured a lot over the years and now offers some very flexible options for grabbing screenshots. I love the scrolling window options, although there's a free Chrome plugin that does that as well.\nOn Linux, I use the free Shutter application, it does everything I need it to do on Linux (which is usually just screenshots of terminal windows or application screens. If I need a full length browser window capture, I'll usually just grab it from a Windows PC or Macintosh.\nOne thing these tools don't do is give you an easy way to hide or replace confidential information in screenshots. In Snagit I use the Snagit Editor to blur out or color-fill areas of an image to hide information I don't want displayed in the screenshot. I sometimes use Corel's PaintShop Pro to do the same thing, the only difference is whether i'm doing this as part of snapping a screenshot or simply editing a file later. These editing tasks, by the way, are the limit of my image retouching capabilities and I'm very glad that both tools make this easy.\nA feature I'd really like in Snagit, and its funny that I've never thought to tell them (TechSmith) this, is that I'd really like to be able to somehow select text elements or inputs on a screen and tell Snagit to blank them out or replace selected content during the screen capture. This way, I can capture my screens and blank out the private information in one seamless process instead of having to capture the image, open an editor, and make my changes. If you're listening TechSmith, make this happen please?\nWhen working with screenshots of web pages or web applications, there is a relatively easy way to get change the content on the page before capturing the screenshot. I've noticed that a many  writers don't use this technique, so I thought I'd write about here and show you how it works.\nUsing your browser's developer tools, you can edit the content of any page. When you save your changes, those changes reflect immediately in the browser window. Then, when you take the screenshot, it shows whatever you want it to show on the page - hiding personal or confidential information you don't want in the screenshot.\nLet me give you an example, since I work for Microsoft, I thought I'd use the Azure portal as an example. If you look at the following figure, you can see that the portal thinks my email address is joe dev at acmedynamite dot com and my user name is Joe Developer. Those aren't my actual account details, I simply changed them before taking the screenshot.\n\nMicrosoft Azure Portal (modified)\nLet me show you how I did it.\nFixing URLs first\nIf you're going to include the browser's address bar in your screenshot as I've done in the previous example, you must make sure you edit the URL to remove any personally identifiable information (PII). If, for example, your site's URL was something like this:\nhttps://myimportantsite/somefolder/login&amp;user=someconfidentialusername\nYou'll should edit out the PII, replacing it with useful, but non-confidential data. For example, many sites use Globally Unique Identifiers (GUID) in URLs to help the server identify the resources, and those often end up in URLs. If you look at the previous figure, you can see that the name for an automatically generated mobile app resource I created in Azure consists of the word mobile plus a GID. Since the full, internal name for resources you use in your app are something you won't want others accessing, when I take a screenshot of a page loading that particular resource, I'll simply let the page load, then edit the URL displayed in the browser, removing any information others can use to access that resource, before taking the screenshot. The edited URL doesn't affect anything, all the existing links on the page will continue to work as expected.\nThe only problem you'll have is if you put focus on the browser's address bar and press the enter key (triggering a load of the edited URL). Unless what you've typed is a valid URL, the browser won't be able to find the page and you'll see an error.\nAnother option is to take your browser screenshots omitting the browser chrome (including the address bar). When you do this, all you get is the rendered page, so you won't need to worry about PII from the page address appearing in your screenshot.\nGoogle Chrome Dev Tools\nTo 'fix' content on a page using the Chrome browser, open the browser to the page you want to screenshot. Next, open the Chrome developer tools (press Ctrl-Shift-I on Windows) then select the Elements tab (highlighted as step 1 in the following figure).\n\nChrome Developer Tool",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "My First Digital Hotel Key",
  "date":"Fri Feb 16 2018 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1518825600,
  "url":"/posts/2018/my-first-digital-hotel-key/",
  "content":"I'm staying in San Francisco this week and when I checked into my hotel, they offered me an opportunity to use a digital key to get into my room. That seemed like a fun and interesting thing to do, so I said yes and began the process.\nFor some bizarre reason, Hilton requires some legal process to get my key; I had to agree to some terms in order to use this option (I don't understand why, and I didn't read them before I accepted them). I eventually got an email letting me know that my digital key was being generated and would be delivered to my phone (actually the hotel app on the phone) once my room was ready. When I got to my hotel and opened the app, I saw what you see in the following figure; a button in the lower-left corner with an option to open my room using the app. Nice!\n\nDigital Room Key 1\nWhen I tapped on the key, I was instructed to get close to the door I wanted to open as shown in the following figure. I'm assuming it's using Bluetooth Low Energy to detect if I'm close to the door, and hopefully it knows which door I'm close to.\n\nDigital Room Key 2\nOnce the system recognizes the phone/app, the page/screen changes to a button you can use to actually open the door. God forbid that you'd be in a hurry, as this process takes much longer that it takes to pull a key out of your pocket and use it. If there was a rapist or robber on your tail, you'd be a victim before you could ever have the door open.\n\nDigital Room Key 3\nThe challenging aspect of this feature is that this process only works when all of the intermediate parts work as well. When I got back from breakfast this morning, I opened the app and the app hung with a incompletely rendered screen. After poking around for a short while (closing and reopening the app a couple of times), the app finally told me that there was a problem and it was on the hotel's end of things. Comforting information, but not even at all useful as I'm standing outside my room and can't get in. Sigh.\nThe problem eventually resolved itself and I could get into the room, but what options did I have in light of this failure? Call the hotel and hope they could get me into my room remotely? Would they even do that? Doubtful. I imagine they'd either send someone to the room with a key or I'd have to traipse down to the hotel lobby and get a physical key. Either way I'd probably have to prove who I am even though the app knows who I am and where I am.\nWhen I went to the gym this morning, a sign outside the door said I could find the fitness room key in the app. I'd not seen an option for that in the app, so I stood outside the fitness room for a few minutes fumbling around in the app until someone left and I could just go in their the opened door.\nIt turns out that that little unlabeled blue key icon on the middle-top right of the screen opens some options for the key system. You can either access your room key or the key manager (whatever that is).\n\nDigital Room Key 4\nI only needed one key, so I had no idea what the key manager would be used for. I imagined I'd use it if I needed keys to two rooms (when I'm traveling with my family for example). Well, this inappropriately labeled option grants me access to other keys I'll need when I'm staying at the hotel as you can see from the following figure.\n\nDigital Room Key 5\nFrom a UX standpoint, the list of public keys should not be hidden away under a double sub-menu, those options belong on the bottom of the main key screen or under a separate, but easy to locate, tab on the key page. It should take one tap, or at worse two taps, to get to the fitness center key. In this app, it costs me three taps at a minimum, but only if I'm able to figure out in a hurry what that key icon means to me.\nShould that icon be a key, or something that says “other keys”? Which would enable the app user to get to other keys the most quickly? Yeah, the latter option. Even using a single key icon here is misleading, a simple icon with a stack of keys or a key ring would have helped me understand more quickly what that particular button was for.\nThis system works, more or less, but could use some TLC (tender, loving care). This process is a great example of what happens when the person who designs and implements a system didn't take the time to validate the UI with the everyday user. A little time with actual users would have helped them understand that the UI metaphors they selected simply didn't work.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "American Airlines Flight Summary",
  "date":"Thu Dec 21 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1513900800,
  "url":"/posts/2017/american-airlines-flight-summary/",
  "content":"American Airlines sent me an interesting infographic this week, it summarized all of my flight activity for the year. It was interesting to see that with all of my flights, I flew enough to circle the globe twice this year. Surprising, until I remembered that I flew to Israel and Slovakia this year. No surprise that Seattle was my primary destination considering I now work for Microsoft. Here's the infographic.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Two Dead Hard Drives",
  "date":"Sun Dec 03 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1512345600,
  "url":"/posts/2017/two-dead-hard-drives/",
  "content":"My desktop PC (yes, I use a Windows Desktop for most of my personal work) had a hard drive crash a few weeks ago. This particular PC is three years old, so I expected to see some failures. It wasn't too bad as my system has a 512 GB SSD as its boot drive, but an 8 TB RAID array for all my apps, data, games, etc. I ordered a replacement drive and was quickly back in business.\nWeirdness ensued when I tested the 'bad' drive using the manufacturer's diagnostics and it passed with flying colors. I assumed that the original failure was just a fluke, so I ran the tests a few more times and set the drive aside to use when another drive failed.\nA week or so later, another drive in the RAID array failed. Knowing I had a 'good' spare lying around, I swapped the drives and got to work. Unfortunately, the array came back up, but then quickly failed again. Since I knew the drive tested good, I started looking for other sources for my problem.\nI swapped all my drive cables, split the array across two power supply rails, but the problem persisted. At this point, I ordered a new motherboard and installed it only to find that the problem persisted. Thinking through this, I started swapping the drives around and noticed that the problem moved with the drive. I then swapped the old, bad drive back in and the problem persisted. Crikey, two bad drives.\nI should have swapped the drives around before I ordered the motherboard; if I'd done that, I would have noticed that the failure followed the drive, eliminating the possibility that it was a motherboard problem. My second failure was assuming that the original failed drive was still good It turns out that the drive works when first connected, but then fails a while later.  The evidence showed that, but I ignored it when the drive passed diagnostics.\nI finally ordered another replacement drive, plugged it in, and I'm all set; everything is working as planned.\nI also used this as an opportunity to format my system and do a clean installation of Windows. This is the only system I've EVER upgraded (from Windows 8 to Windows 10, what happened to Windows 9, I can't tell you), and I was having some problems. The biggest of which was that my Windows Store instance was corrupt, and I couldn't install or upgrade any Windows Store apps on the system.  I encountered some problems with the re-install, I'll share those experiences in my next post.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Started Writing for HackSpace Magazine",
  "date":"Sun Nov 26 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1511740800,
  "url":"/posts/2017/started-writing-for-hackspace-magazine/",
  "content":"A few months ago, the folks at the Raspberry Pi Foundation asked me to write a series of articles on Arduino development for a new magazine they're creating. The magazine is called HackSpace Magazine, and the first issue is available (free) now.\nMy first article starts on page 82; its an introduction to coding for the Arduino platform.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "My ReactiveConf 2017 Sessions",
  "date":"Fri Nov 17 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1510963200,
  "url":"/posts/2017/my-reactiveconf-2017-sessions/",
  "content":"\nSoon after joining Microsoft, I accepted an invitation to deliver a presentation at ReactiveConf 2017. My manager had a speaking slot, but due to a promotion to a different team, he was no longer able to fulfil his commitment to the conference.  \nReactiveConf is held in Bratislava, Slovakia; it is a dual stage conference focusing on development topics; mostly web, but some mobile. Presenters came from all over the world (most from the US), so there was a good variety of topics on the agenda. Apparently the conference grew to more than 1,000 attendees this year.\nI brainstormed a topic with a colleague, and quickly submitted my session title and abstract along with my bio and photograph. For my session, I wanted to do something with React Native and Visual Studio App Center (the Microsoft product I work on), so I decided to show how to use Visual Studio App Center's CodePush and Push services to implement A/B testing in a React Native application.\nTo make this work, you publish multiple versions of your React Native application into different App Center CodePush deployments. With those in place, you use the App Center Push service to send a push notification to multiple devices, inside the notification, you include a custom object containing the Deployment ID for the version of the application you want the device to use. On receipt of the notification, code in the application uses CodePush to pull down the specified version of the app content. At the conclusion of the A/B test, you simply send another push notification to the devices, resetting the Deployment ID to the app's original version.\nI've attached my presentation at the bottom of this article, for more details on my session, check out my blog post on the Visual Studio App Center blog (coming soon).\nhttps://youtube.com/watch?v=X9iqnovPGyY\nEven though I only planned on delivering one session at the conference, I found ways to deliver some additional sessions:\n\nThe conference scheduled several quick, 10-minute lightning talks on a variety of topics, so I volunteered to deliver one. They had an online vote to see if anyone wanted to see my presentation, and I got voted in. In my session (they only allocated me 4 minutes, but that was enough) I demonstrated how to use a new feature of Visual Studio Code to enhance developer productivity. You basically add [//@ts-check to](mailto://ts-check to) the top of any JavaScript file, and Visual Studio Code applies the TypeScript compiler to the file and highlights JavaScript errors you wouldn't know about otherwise.\nThe third day of the conference was Festival Day, and was held at a local university. The conference asked me (and some other presenters) to participate in an inspirational talk, to describe to University students how I got started in this field and what inspires me. There was no preparation for this session, I merely talked about myself and answered some questions. You can watch the session at https://youtube.com/watch?v=ivCI2YJPCDQ&amp;mc_cid=e04ae2b8ed&amp;mc_eid=7c7ec0b350.\nIn my final session, I delivered a thirty-minute session about the state of mobile development, you can watch the video at https://youtube.com/watch?v=DrHx9ei_-2o&amp;feature=youtu.be&amp;mc_cid=e04ae2b8ed&amp;mc_eid=7c7ec0b350.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Visual Studio App Center Launched Today",
  "date":"Tue Nov 14 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1510704000,
  "url":"/posts/2017/visual-studio-app-center-launched-today/",
  "content":"With much fanfare, Microsoft launched Visual Studio App Center today.  This is the product team I work on at Microsoft.\nRight now, App Center is the Visual Studio Team Services build service coupled with evolutionary versions of the Xamarin Test Cloud and HockeyApp. Today, App Center offers Build, Test, and Distribute in the cloud plus crash detection and analytics. You can sign up for a free account on App Center at https://appcenter.ms.\nIf you watched the announcement, you may have noticed that we highlighted additional capabilities for App Center; things like Identity and Tables. Those capabilities aren't part of App Center today, but something that I'm working on going forward. My day job is helping to understand which additional capabilities do we expose through App Center. If you have any insights you'd like to share, please let me know.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PhoneGap Day 2017 Presentation",
  "date":"Thu Nov 02 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1509667200,
  "url":"/posts/2017/phonegap-day-2017-presentation/",
  "content":"The week following my session at NCDevCon, I was fortunate enough to be Microsoft's representative at PhoneGap Day 2017 (US). Microsoft hosted the event in our Times Square (NY) offices, so I was asked to be the onsite host. It was a lot of fun and I got a chance to hang with a lot of great people.\nI've not been involved with the Cordova project for some time now, I interacted with the Cordova team while working as an Analyst at Forrester, but in the year that followed, I didn't do a lot of mobile development. In my role at Microsoft, I'm responsible for our JavaScript Mobile development tools (the Cordova and React Native extensions for Visual Studio Code), so it's nice to be working with Cordova again.\nFor my session, I delivered a presentation on how to use Cordova Simulate to streamline manual testing of Cordova applications. Cordova Simulate is an open source project sponsored by Microsoft. It's an evolution of the Ripple Emulator (do you remember the Ripple Emulator?), but one that 1) was actually released, and 2) actually works. Microsoft uses Cordova Simulate in its Tools for Apache Cordova (TACO) and it's also bundled in the Apache Cordova Extension for Visual Studio Code. It enables you to simulate a Cordova application in the browser, but with complete simulator control the core Cordova plugins. Check out the project when you get a chance, it's pretty cool and easy to use. I'm going to write a blog post on Cordova Simulate some time in the near future.\nhttps://youtube.com/watch?v=3YEAqB_ujeg\nFor my session, I also demonstrated how to add support for Cordova simulate to third-party plugins. I took my Carrier Plugin, and demonstrated how to add code to it to enable it to work with Cordova Simulate. You can find the source code from the demonstration on Github.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "NCDevCon 2017 Presentation",
  "date":"Wed Nov 01 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1509580800,
  "url":"/posts/2017/ncdevcon-2017-presentation/",
  "content":"A few weeks ago, I presented a session at the NCDevCon event in Raleigh. I've attended the conference the last few years and really enjoyed it, and I was excited to be asked to deliver a presentation. The conference is a locally run developer conference that's been running for, I think, 9 years now. I discovered the conference a few years ago when one of the presenters, Simon MacDonald from the Cordova/PhoneGap team, tweeted about presenting at the conference. Presenters come from all over the country, sometimes from out of the country, to present, so there's always some pretty interesting topics.\nAnyway, for my presentation, I decided to present on Building Mobile Applications using Open Source Frameworks. I thought I'd leverage my experience with Cordova and Ionic while at the same time using this opportunity to learn more about NativeScript and React Native. I bit off way, way more than I could cover in my short 50 minute session, but it was fun. I basically built the same application four ways, one for each target I listed above. You'll find the presentation file as an attachment to this article.\nYou can find the project source code I demonstrated on Github. I posted the slide deck at slideshare.net, but I can't find it there anymore. I'll update the link tomorrow and update this blog. Finally, a video of the presentation can be found on the conference's YouTube Page.\nDon't laugh too hard as you watch me try to stuff two hours of presentation materials into 50 minutes. Next year I'll make sure to pick a topic I can easily cover in the allotted time.\nhttps://youtube.com/watch?v=nYHdbvPewu4\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Presenting at NCDevCon 2017 This Weekend",
  "date":"Mon Oct 02 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1506988800,
  "url":"/posts/2017/presenting-at-ncdevcon-2017-this-weekend/",
  "content":"Since joining Microsoft, I've picked up speaking slots at several fall conferences. This weekend I'll be presenting at NCDevCon 2017 (https://ncdevcon.com/), a community event held in Raleigh. I attended the previous two years and really enjoyed this conference. This year, I proposed a session, but wasn't selected. One of my Microsoft colleagues changed positions recently and dropped from his session, so the event organizers asked me to pick up his slot.\nI'll be covering Cross Platform Mobile Development Using Open Source Tools, so I'll present content on Apache Cordova and Ionic. I'm also going to cover JavaScript-driven native development in my session, so I'll be making apps using NativeScript and React Native, It'll be fun.\nI'll publish a link to the presentation and sample source code after the event.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Amazon Alexa is Not Artificial Intelligence",
  "date":"Tue Sep 05 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1504656000,
  "url":"/posts/2017/amazon-alexa-is-not-artificial-intelligence/",
  "content":"\nThis post copied from my World Without Apps site.\n\nI’ve been reading a lot of articles lately about digital assistants like the Amazon Echo and Google Home. In my reading, I’m seeing more and more writers categorize these simple devices as Artificial Intelligence (AI). While I’m not an expert in the field, merely an interested party, this makes no sense at all.\nAmazon Alexa isn’t AI; it's a system that parses a voice request and decides what to do with the request based on the specific code that's been written for it to respond to the specific query, or queries like it. Alexa can only do what it's coded to do, and nothing else. You can prove this pretty quickly by asking it a question that requires intelligence (the I in AI) to answer and you’ll quickly get an “I don’t know what to do with that” response.\nNow, Amazon has done a lot of innovation around delivering a system that gets better over time at being able to understand what you’re asking for, but that’s not intelligence, that’s better Natural Language Processing (NLP). The better it gets at understanding your query, the better the Alexa development team can get at writing code that deals with that particular type of request.\nAs I’ve written here before, Alexa is code-bound - it can only do what it's coded to do. As a developer, I can define some phrases I’m interested in dealing with, then write some code to have Alexa execute whenever it hears any one of those phrases uttered by an Echo user. If someone (a developer) hasn’t defined the phrases AND written the code to respond to them, then Alexa can’t do anything with it.\nThat’s not Intelligence.\nNow, the folks at Amazon have coded fallbacks, right? But they’re still hand crafted code to deal with a specific situation. If you ask Alexa to do something it doesn’t know what to do, it does a quick Internet search on the phrase it heard you say, and posts the search results to the Alexa App.\nAgain, that’s not Artificial intelligence.\nTry to have a conversation with it, and you’ll fail miserably. Some developer has coded cheeky responses to specific types of general purpose questions (like “How are you?”) but those are still hard-coded responses to specific queries. Alexa knows how to tell me a Star Trek joke, only because someone coded it to do so - not because it is intelligent. Correct me if I’m wrong, but Its not hearing “Joke” and “Star Trek” then figuring out if the jokes it has fit the bill, I imagine some developer built a database of Star Trek jokes, or at least gave Alexa a list of sites where it can go to find Star Trek jokes. That’s not intelligence.\nWhat finally drove me to write this post was two articles in this month’s MIT Technology Review magazine (Volume 120 | no. 5), one is called Alexa, Understand Me and the other Growing Up with Alexa. The first article repeatedly glorifies Alexa as an AI, explaining all sorts of ways that the Alexa team uses data to fine tune its NLP and explaining how that makes it a better AI. Its a very interesting article about how big of a challenge it is to make Alexa seem smart, but nothing about what they’re doing is AI. The second article deals with Alexa as what it is: a personal digital assistant. The difference between the two articles and how they portray Alexa as two completely different things makes me believe that the no editor at the magazine read both articles. If they had, they probably wouldn’t have published both of them as they’re contradictory in their definition about what they’re writing about.\nA quick Google search on “Intelligence” came up with this definition:\n“the ability to acquire and apply knowledge and skills.”\nAlexa does this - it acquires skills and applies them, but not through its own actions. Developers define skills and publish them to the Alexa service. Alexa’s NLP capabilities connect what’s asked with the available skills. That’s not intelligence, that’s coding. That’s a piece of software responding to the logic in its code.\nArtificial Intelligence is about intelligence. For Alexa to be AI, it would need to be able to do something it wasn’t coded to do. That’s intelligence. Figuring something out. When Alexa can figure out how to do something it doesn’t know how to do using the things it does know how to do as building blocks, then you can make the argument that its intelligent. When it can make leaps of understanding, then its intelligent. As long as it can only do what it has been coded to do, then it is an appliance and nothing more.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Artificial Intelligence"
  
  ]
  },

  {
  "title": "When the WWA Overlaps the Physical World",
  "date":"Sun Aug 27 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1503878400,
  "url":"/posts/2017/when-the-wwa-overlaps-the-physical-world/",
  "content":"\nThis post copied from my World Without Apps site.\n\nI started a new job at Microsoft a few weeks ago, and, surprisingly, one of the first things they handed me was an Apple MacBook Pro. This isn’t standard procedure, but in my role, I’ll be working with development tools for Android and iOS applications, so a MacBook is required to do (almost) anything with iOS. Anyway, as I setup my Mac, I was having trouble dragging files and apps around. There was something weird going on, but I realized pretty quickly that I had to have a mouse to be productive. I have a mouse here with me in Redmond, but it's a USB mouse and, well, the MacBook no longer exposes regular, everyday USB ports. Sigh.\nAfter work, I quickly headed to the nearest Apple store and purchased a mouse. As I checked out, the sales associate asked me to confirm my email address where they could send the receipt. Right there on his iPhone screen was my new Microsoft address I’d only had for a few hours now. What happened? How did they have my Microsoft email address? I’m certain Microsoft didn’t share it with them, so who did?\nMe, I did it. I’d completely forgotten that I setup a new iTunes account using my work email address and my for-work credit card. I did that because Apple won’t allow you to have an iTunes account without providing a credit card number.\nThe connection here to the World Without Apps (WWA) is a little shaky here, I know, but as this happened, I was immediately struck by how my online life was bleeding into the physical world. It should not have surprised me that Apple could lookup my email address based on the credit card I was using, that’s easy. But in this WWA, how far will this go?\nHow long before your personal search history starts showing up on store POS (point of sale) terminals? Can you imagine checking out at Macy’s and the clerk saying something like “hey, I noticed you searched for underwear the other day, did you know they were on sale? Here’s a coupon” or how about “Hey, I noticed you saw Jonny Lang last week, did you see his new line of skinny jeans we have for sale?”\nThis is actually one of the possible side-effects of our government’s removal of restrictions on how ISPs can use your historical browser history. How far will it go? What happens when an agent (a computer program) interacts with the store you’ve entered and they share data? That clearly has strong benefits from a streamlining the shopping experience standpoint, but where could it go wrong? Who decides how much information the store should have access to? You do, but how do you do that in the WWA? Nobody knows.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
  ]
  },

  {
  "title": "Working at Microsoft",
  "date":"Tue Aug 15 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1502841600,
  "url":"/posts/2017/working-at-microsoft/",
  "content":"I started working at Microsoft last week - and there was much rejoicing (an obscure Monty Python reference). I've joined the Azure division as a Principal Program Manager on the team building Visual Studio Mobile Center (Microsoft's cloud service for mobile developers). I'm very excited about this new role, as it allows me to get back into the mobile development space, and lets me be a developer (instead of a tester) again. I'll write more about what I'm working about as I get more involved in the product.\n\nMicrosoft Visual Studio Mobile Center\nFor the last year (literally a year and a week) I've not had permanent employment. During this period I did some freelance writing for Perfecto Mobile (mobile testing tools) and AT&amp;T (IoT Platform), and I also did some contract work for Microsoft and Hewlett Packard Enterprise. At Microsoft I worked on the Visual Studio documentation team, updating the Visual Studio Tools for Apache Cordova (TACO) docs for Visual Studio 2017. At HPE, I was the Product Manager for their Mobile Center product (an execution environment for mobile application tests on physical devices and emulators).\nI think its pretty funny that I went from working on one company's Mobile Center to another company's Mobile Center. HPE's Mobile Center is focused entirely on providing an execution environment for app tests running on physical devices and emulators. Microsoft's Mobile Center does have a testing component (although I won't be directly involved in that), but is focused more on providing services and capabilities for developers building mobile apps.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Give Me a Library, Please",
  "date":"Sun Jul 16 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1500249600,
  "url":"/posts/2017/give-me-a-library-please/",
  "content":"I've been doing a lot of work lately on several IoT projects. For a while last year, I worked on some documentation for an IoT platform, but for the most part, I've been working on some personal projects. Recently, I've been trying to build a better power timer – using relays and a microcontroller to turn a light on and off on a schedule, even using sunrise and sunset as triggers (you can see some of my work here and here). I recently discovered some relay boards for the Raspberry Pi platform, and started working with them. My experiences with these boards, and the sample code provided for each, incented me to write this post today.\nWhen you're working with someone else's hardware, chances are that you don't know how to 'use' the hardware in your project. That's why vendors typically include some sample programs to show you how to work with their board, right? The problem is, these sample programs are typically written by a hardware guy trying to show that the board works instead of being written by someone trying to show you how to use the hardware in your project.\nWhat these vendors must do is make a list of the core things a developer will want to do with the hardware, then build code that quickly and easily enables developers to do those things. Once all that code is written and tested, vendors should publish the code as stand-alone libraries that developers can easily plunk into their apps and use.\nInstead of the huge Kitchen Sink app, with UI and functional code intermixed, pull out the functional code into stand-alone libraries for easy consumption. Then, build a separate UI or interaction app that uses the library to interact with the hardware. That way, developers have an easy way to determine how to interact with the board from their applications (by looking at the library code) and an easy way to interact with the hardware (the UI app) to make sure it works or to see how it works. This simple separation of concerns dramatically increases a developer's (experienced or inexperienced) ability to come up to speed with your hardware.\nAs an example of what not to do (and what prompted me to write this post), take a look at the code for the ModMyPi PiOT Relay board at https://github.com/modmypi/PiOT-Relay-Board/blob/master/piot5.py. In this example, you'll see 424 lines of code for this relay board; I'm guessing here, but you'll see, I'll bet, more than 300 lines of UI code and only about 30 lines of code that actually show you how to work with the relay board. It took me a while looking through the code to find those 30 lines that I needed to learn how to use the board in my projects. Its those 30 lines or so that I want the developer to pull out into a library for me – to make it easy for me to see how to use the board.\nIn this example, it gets even worse. This relay board has 4 relays, and the only code the developer provides is code to toggle all or individual relays. Thinking through the use cases, developers may want to turn a relay off or on as well. What good is the ability to toggle a relay when I'm not certain of the relay's status?\nWhat I did was think through how an app will want to interact with the board and came up with the following:\n\nTurn a relay on\nTurn a relay off\nToggle a relay (on to off or off to on)\nTurn all relays on\nTurn all relays off\nToggle all relays\nGet Relay status (is the specified port on or off?)\n\nThis list is what any project may need to do with this board, so that's what must be coded in the example application to help developers, especially inexperienced developers, can get up and running quickly. With that in mind, I published my own library for this board on Github. You'll find functions for each of the items in the list, and you'll be able to add this library to any project, initialize it then interact with its relays as needed.\nThat's how you enable developers to use your hardware: make it easy for them, not by making it hard for them!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Hacking AI for Fun and Profit",
  "date":"Thu Jun 08 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1496966400,
  "url":"/posts/2017/hacking-ai-for-fun-and-profit/",
  "content":"\nThis post copied from my World Without Apps site.\n\nI knew all along that AI was a component of the World Without Apps. What I didn’t expect was how quickly AI-driven actions would become a home-grown option. I subscribe to The Mag Pi magazine (a publication from the Raspberry Pi Foundation) and even got my first project published in the current issue (https://www.raspberrypi.org/magpi/issues/58/).\nIn the previous issue, the magazine included the complete Voice Kit AI project from the Google AIY (AI Yourself) project – basically a complete Google Assistant including an enclosure, speaker, button, Audio HAT, and more. My son and I quickly assembled the project, and now he has an almost Google Home device in his bedroom. This is absolutely interesting because Google funded sending thousands of these devices all around the world, but more interesting is that the core project here is extensible. The project runs on a Raspberry Pi, and you can add commands to the Google Assistant project code. Once you do that, you basically write the code to respond to your specific voice commands and you can make this device do anything, absolutely anything.\n\nYour regular Google Assistant go to the cloud for execution (searches, weather reports and so on), but, if you connect some specialized hardware to it (not something specific, but any hardware you can control from the Raspberry Pi) and correspondingly add your own code, suddenly your project becomes much more interesting.\nFrom a Maker standpoint, this dramatically enhances the types of projects that I can make with this thing. I no longer have to deal with ANY of the complexities of voice interaction, the platform (Google AIY) takes care of that for me. All I have to do is connect my hardware, add the command to the acceptable command list, write some code, and I’m all set.\nThis will ultimately take us to something I’m worried about: AI everywhere. When companies (and hackers) start embedding AI into everything around us, suddenly we have multiple systems all listening for commands and stepping over each other. I got a good taste of this while watching this Spring’s Google I/O keynote. Every time the presenter said “OK Google” to demonstrate a new capability on stage, my local Google Home device would wake up and answer. I had to put my phone in my pocket during the presentation so it couldn’t hear and answer as well.\nWhat do you do when your car and phone both have AI capabilities? How does each device know it’s the target of the query? Will I then need to preface every query/command with the name of the target device I’m targeting? Probably at first, but ultimately, we’ll get to a single, overarching AI that understands what it can interact with locally. You’ll speak to the ceiling or your thumb, or whatever, and an available, compatible device will perform the action for you, whatever it is.\nThat’s where this is ultimately going, I’m certain of it. When that happens, we’re in the World Without Apps.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Natural Language Processing"
  
  ]
  },

  {
  "title": "Facebook and The World Without Apps",
  "date":"Sun Apr 23 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1492992000,
  "url":"/posts/2017/facebook-and-the-world-without-apps/",
  "content":"\nThis post copied from my World Without Apps site.\n\nThere’s been a lot of buzz around Facebook – primarily because of the murder that took place on Facebook Live coupled with Facebook’s failure to recognize it and pull down the video in a reasonable time. Apparently Facebook spent a lot of effort building systems to recognize copyright violations (which causes them issues) and little on technologies that recognize harmful acts (this causes victims issues, but not Facebook directly).\nFacebook’s ability to recognize a murder in progress wouldn’t have helped the victim here – he would have been dead before the police could have gotten there. However, if Facebook focused their attention on determining the scope of a live session, then in abuse or rape scenarios, they’ll be able to get help there before the ‘event’ is over. A valuable use of the technology, I imagine.\nAnyway, back to the WWA.\nAt Facebook’s conference this month, Facebook highlighted their plans for augmented reality. Augmented reality is a different variant on the World Without Apps. Instead of interacting with your environment (your home, your car, your office, etc) or your smartphone via voice as I’ve highlighted in this site, with Facebook’s approach, you’ll socialize in a virtual reality world. This ‘world’ is essentially served by an app, and anything you do in that world will be exposed by an app running in the cloud somewhere (exposed through your virtual reality goggles). Extra capabilities provided by third parties? Basically extensions to the app. So, it feels like where Facebook is going is the opposite of the WWA – they’re planning (if I can oversimplify here) one big app you ‘live’ in…virtually.\nWhen interacting with the ‘real’ world, Facebook’s plan is that you’ll do it through special glasses that add a computer screen in front of your eye or on a wall or table. Initially this feels like an extension of the WWA, but it’s not. Zuckerberg said “We don't need a physical TV. We can buy a $1 app 'TV' and put it on the wall and watch it.” So Facebook is still focused on apps; in this case, selling you additional functionality to use in an augmented reality world.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
  ]
  },

  {
  "title": "Implemented Google Wi-Fi",
  "date":"Fri Apr 21 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1492819200,
  "url":"/posts/2017/implemented-google-wi-fi/",
  "content":"I had an interesting SMS conversation with my son the other day. The conversation went like this:\n\nI was at a concert with my wife (we saw Jonny Lang) and we noticed that the kids were watching a show on the Apple TV (I'll explain how later) when they were supposed to be in going to bed, so I turned off Wi-Fi to the Apple TV. Here's the story...\nMy brother in law recommended I get the Linksys WRT 1900 Apache Cordova Router. My brother in law liked how it allowed you to configure a separate guest network and some other features, so I got it and put it to work.\nUltimately, though, I didn't like the results I got with this router. True, it allowed me to implement a guest network, but bizarrely the guest network had different passphrase requirements than the primary network. The primary network allowed me to set a passphrase containing spaces, but for some ridiculous reason, the guest network password couldn't handle passphrases, it had to be a password instead (with no spaces). It had other interesting features, like the ability to set priority devices and some other stuff, so I used a guest password I wasn't happy with and left it in place.\nFast forward a couple of years later and al of a sudden, I can't connect to the Wi-Fi network in my office with any of my mobile devices. I'd reboot the Wi-Fi hotspot or reboot the devices and get on the network, but ultimately it wasn't working. Gone are the days where I can troubleshoot a network, I just don't have the bandwidth for it anymore, so I decided to swap out the hardware for a better solution.\nI'd been looking at the Google Router for a while now; a friend uses one and configured it to use the OpenDNS service for name resolution (and site blocking). I thought that might be a good solution, but then I started reading about Google Wi-Fi and its ability to implement a mesh network. I decided to give this solution a try and purchased and setup a three pack of the devices in the house.\nMy office is in an outbuilding, and I thought I'd leave my hotspot in my office, but when I setup the new network, I disconnected the hotspot in my office and noticed that I had good coverage from the house. So, three devices, distributed through the house was enough to cover my office and workshop as well. Nice!\nThe setup process is really simple, you install the first device and connect it to your cable/DSL modem using a standard Ethernet cable. When you fire up the app, it walks you through setting up the network, creating a primary and guest networks – both allowing passphrases (woohoo!), of course. Next, you add each additional unit, and let the app configure its Wi-Fi mesh.\nIt only took a few minutes and I was all setup. A quick test with my mobile devices and they all connected just fine to the new network. Even my desktop PC, a couple of Raspberry Pi devices and my smart devices all connected to the new network automatically. I didn't have to restart or muck with it in any way. Nice!\nI started poking around in the Google Wi-Fi mobile app (Google insists in calling it WiFi, but since that's not how you spell Wi-Fi, I'm not going to use their spelling); the app opens to a view of your network:\n\nFigure 2\nHere, I can quickly tell whether my Internet connection is up. I can view the status of my Wi-Fi units, and I can view all of the devices on the network (wired or Wi-Fi).\nWhen you tap on the Wi-Fi points, you'll see each of the units and the current device's connectivity to each. In the following image, you can see that I have a good connection to the Family Room and a poor connection to the 'Hallway' device. This is good as the Family Room device is closest to me, but even if that one goes down, I can still see signal from the device that's furthest away.\n\nFigure 3\nYou can also test the network, notice the 'Test Mesh' button in the bottom-right corner of the figure. When you tap on the button, the app begins a network check:\n\nFigure 4\nFollowed by a Mesh check:\n\nFigure 5\nAnd finally the Wi-Fi network (which I'm not showing). Anyway, there's lots of information about the network which is really useful and very easy to use (especially compared to the Linksys solution I used previously).\nWhen you access the Devices section of the app, you're presented with a list of all of the devices currently using the network. When you open a device, you can view the device's usage of the network (which is useful) but you can also edit it's display name, enabling you to name devices based on how you view the device, not the way the network sees the device. So, I've named my Amazon Echo devices based on where they're located (kitchen, office, etc), my computers based on my name for them and so on. At the end of this process, I had a complete list of devices I could view, all named the way I wanted them named. Cool stuff.\nOn to the SMS conversation I showed you at the top of the article. One of the things the app allows you to do is setup Family Wi-Fi settings. Here you can define groups of device",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "WebWatcher - When Software Companies Get Greedy",
  "date":"Tue Apr 11 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1491955200,
  "url":"/posts/2017/webwatcher-when-software-companies-get-greedy/",
  "content":"I have teenage twins in the house. When I first got them smartphones, my wife and I wanted to be able to see everything they did on their phones to protect them and, well, to keep an eye on them. I looked around and WebWatcher was a highly rated solution. My sister had a coupon, so I purchased a license, installed it, and started monitoring my kids' smartphone activities. My wife and I also told the kids that we'd be watching everything they do on their phones, so there'd be no surprises when I started asking them about their online activities.\nI pretty quickly learned that I'd made a mistake with my purchase.\nThe capabilities WebWatcher provides are useful and work fairly well, but the parent portal is very cumbersome to use and looks like it was created with really, really outdated tools. It has a dated look that seems out of place with all of the beautiful web interfaces available today. Apparently WebWatcher isn't using its income to improve the UX or UI of its tools. As you can see in the figure below, the admin UI looks very…web 1.0 app circa 2001.\n\nFigure 1 – WebWatcher Admin Console\nWith all of the amazing, data-aware HTML and JavaScript frameworks available today, you'd think they'd be able to deliver a better UI.\nNext, I realized that WebWatcher only holds collected data for a short period of time. In order to be able to view the history of your child's activities, you have to pay for additional storage to store your data. They don't mention that when you're buying the license, but begin pestering you immediately after your purchase with emails offering to increase your storage for a fee. I finally had to turn off most email alerts just to get them to stop begging me for additional money.\nThis was the first indication of WebWatcher's greedy nature. As you can see from Figure 2, it will cost you another $10 per month ($120US per year) for 100 MB of storage. If your kids take a lot of photos, that storage will disappear pretty quickly.\n\nFigure 2 – WebWatcher Storage Pricing\nIn comparison, Google Drive offers 15 GB of storage for free (15 times more storage than WebWatcher's $10/month offering); yes, free! Amazon Drive offers unlimited storage for $60US (infinitely, literally infinitely, more than what you get for WebWatcher's $120US per year at half the price). Those are big companies, right? These cloud companies have a lot of resources, so they can offer a greater discount on storage right? So let's consider Acronis, a small PC backup company, their $39.99US software product offering includes 1 TB of storage for one year. There's a whole bunch of other companies that offer an amazing amount of storage for much less than WebWatcher offers its customers. iDrive backup solution? 5 GB for free, 1 TB for $70 per year. DropBox offers 25 GB of free storage for anyone.\nAs you can see, WebWatcher's prices are ridiculous when you consider other data storage options.\nNow, their pricing might be high because they're running their own data centers, and can't offer the prices that these other guys do. I get that. What I object to is that WebWatcher didn't mention anywhere in the product information pages that you get limited storage for your account. No mention at all of storage limits and the pricing for additional storage. You can only see these options after you've purchased licenses and have logged into the admin console. That's deceitful.\nThe only reference to storage appears when you add a license to the shopping cart as shown in the following figure. Here, they tell you that you get unlimited data storage for your viewing period. There's no mention anywhere of what your viewing period is. Right now it's 7 days, to view any of your data after that, you have to buy storage.\n\nFigure 3 – WebWatcher Add-on Products\nOf course, my son quickly broke his phone and I had to buy a replacement for it. After poking around on the WebWatcher UI, I was unable to figure out how to revoke the license for my son's current phone and move it to his new on. I had to submit a support ticket in order to be able to figure out how to do it as there's no documentation for this. Apparently, to revoke a license from a device, you have to 'Reset' it. That makes no sense, but apparently that's how the WebWatcher folks view revoking a license from a device. This makes no sense, but it is what it is.\nNow, if you think about it, this is a product for watching kid's activities on their smartphones, so there's a reasonable expectation that you're going to be periodically switching phones. My son broke a few before he got comfortable with it (he's apparently clumsy) and, of course, he has phone envy and always wants a better phone. So, over the last few years, I've had to go in and revoke (oh, I'm sorry, reset) the license.\nWith his latest phone upgrade, I went into the WebWatcher portal interface and tried to revoke (I refuse to say reset) his license. The process failed, and I received the following error:\n\nOne or more licenses are not re",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Android Spam Phone Call Detection",
  "date":"Sat Apr 08 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1491696000,
  "url":"/posts/2017/android-spam-phone-call-detection/",
  "content":"A recent update to the Android OS on my smartphone triggered a new feature I really like a lot. I've started getting more and more spam phone calls on my phone, and Google is now building a list of spam numbers and letting me block them when the calls come in.\nWhen a call comes in from a suspicious caller, after you hang up, Android asks me if this was a spam message. If I want, I can block the number right here as shown in the figure.\n\nFigure 1\nIf I skip this for whatever reason, I can still pull down the alerts list and activate blocking as shown in the following figure.\n\nFigure 2\nThis is a really cool feature, something I'm sure a lot of companies would try to charge you for, but in Google's case, it's just another feature of the OS.\nThis feature blends well into what I'm calling the World Without Apps where more of your day to day activities will be controlled by agents on your smartphone, your home, your car, whatever. In this particular case, I believe this functionality is provided by the device's Phone application, but I'm not sure. Regardless, the UX/UI of this particular feature appears at the system level – the alert pops up as you're answering the phone (through an overlay over what you're currently doing when the call comes in) or through the alerts area of the OS, NOT directly in the Phone application. See?\nI'm curious how long it will be before the OS simply listens to the beginning of the call. If there's a long delay on the other end, before an agent eventually clicks in to begin selling me something, my phone agent can quickly tell its spam, especially when I loudly curse and hang up, and block the phone number automatically if they ever call again.\nUnfortunately, blocking the number directly really doesn't help me. The chance I'll get another call from this same number is slim. It does, however, help other people who get calls from this number, letting them know other people like me think this is spam and offering them a chance to not take the call. That's valuable.\nEventually the technology will get good enough that the calls from these numbers won't even disrupt me, they'll be blocked by the OS and I'll never even know.\nA recent trend in spam calling is to make it look like the call is coming from your own number – the thinking apparently that any blocking software you use won't be configured to block calls from this number. It wouldn't be a hard update to the OS to simply add logic that if the phone gets a call from itself, immediately block it. Right?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Hackers Hacking My Joomla Site's Images Folder",
  "date":"Thu Apr 06 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1491523200,
  "url":"/posts/2017/hackers-joomla-site-images-folder/",
  "content":"For a while now, hackers have been hacking the images folder of one of my Joomla sites (I run sites using both Joomla, WordPress and even a Concrete5 site). I'm not quite sure how they're doing it; I've looked online for others having this problem, but really never found anything. I posted questions on the Joomla forums, but couldn't get an answer.\nThe files show up in the site's images folder, usually just in that folder, but sometimes subfolders as well. The files are usually .jpg files, showing some sort of hacker badge or message; occasionally they're just random images. Sometimes I'll get .txt files, and a few weeks ago, for a couple of days I got .pdf files that, for some bizarre reason, Google quickly picked up in their search results.\nNeedless to say, this was pretty annoying. I don't think anything else on my site was compromised (I checked) and both my ISP's malware detection and SiteGuard didn't find anything at risk on my site. The admin tool I use didn't block the attacks though, so every day, more and more files popped-up in that folder or subfolders, sometimes 30 per day. Sigh.\nI thought perhaps there was something wrong with my hosting account. I ran multiple sites from the same account, so I decided to create a new, separate hosting account for just this one site. At the time, I wasn't using SiteLock, so I added that to this new account thinking that if hackers were doing something weird, SiteLock would catch it. No such luck, no change.\nI attended OSCON a couple of years back (I wish I could attend this year, I really loved that conference) and attended a session about protecting your site from hackers. The presenter (I won't name names right now; you'll understand why in a little bit) did a really good job highlighting different ways hackers got into your site (although mostly targeting WordPress sites) and showed some tools you could use to identify and fix hacks. Cool stuff. I applied some of the strategies and tools to my site to no avail – the hackers kept hacking away.\nI reached out to the presenter to that session and asked for help. She gave me some suggestions to try and I eventually hired her company to completely rebuild my site from scratch. Her team backed up the site, restored it to a new folder and checked everything for malware, cleaned it up and switched my URL to the new instance. No change, anywhere from 5 to 30 images hacked into my site's images folder almost every day.\nI spoke with several technical people at my ISP and got no help. One guy suggested that I that I disable file upload for the site. I'm sure that would have helped, but that would have made it hard for me to add images to my articles, so I put that one aside until I became completely desperate.\nThe kind and helpful people at SiteLock assessed the situation and suggested that I could fix my problem by buying a higher level of protection. Yeah, that would have been useful, but, I'm sorry, I'm not going to plunk down $600 per year to protect my personal blog. That's simply too much.\nI'd been using an old JoomlaShack template for my site for many years. When Google announced that they would be giving mobile-friendly sites preference in search results, I started assessing my existing site's mobile-friendliness and found it lacking. So, I decided to switch templates and make this site mobile-friendly. This was a fun and exciting project. Once I got started, it didn't take me very long to complete the project.\nAs I tested the different parts of my now mobile-friendly site, I was surprised to see that at the bottom of every article list, the site displayed a button labeled “New”. I quickly tested the button and found that I could add new articles to the site – even when not logged into the site! Holy crikey, I think I found the source of my problem!\nI tested a few things, and eventually reset my site's permissions in order to block that particular button. Of course, I broke the site doing this, but at least I killed that button. As I sorted out trying to fix the broken site, I noticed that I was no longer getting image files uploaded to my site by hackers. Woohoo! That particular problem was fixed. I watched the site for a few weeks, no extraneous images. Hackers are finally blocked.\nI think what happened is that this particular site started as a Joomla 1.5 site many years ago. Over the years, I upgraded it all the way up to Joomla 3.6 and I think that during the many upgrade processes, the site's permissions somehow got corrupted. I'm sure there was a major ACL overhaul during that period and I imagine that was the source of my issue.\nOK, so the hackers are blocked, but only because I've hosed up the site's permission settings and even I can't get in. The Joomla.org forums were useless, I got ridiculous responses like “don't mess with permissions when you don't understand them” and “that New button was there because you probably forgot you were logged in” so I had to fix this myself. I quickly determined that t",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Another Ridiculous Input Form",
  "date":"Sun Apr 02 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1491177600,
  "url":"/posts/2017/another-ridiculous-input-form/",
  "content":"Welcome to another installment of Stupid Developer Tricks. In this particular instance, I was filling out a form on a particular web site when I encountered the following:\n\nFigure 1\nApparently the 'form' is a wizard and whomever defined the requirements for this particular form apparently decided that the Next and Cancel buttons (highlighted in the figure) absolutely must be in the exact same place on every pane of the process. Unfortunately, I have a 30 inch monitor, so this doesn't work very well.\nWhen the form first appeared, my first thought was that the page didn't load correctly or hadn't finished loading as all I saw was that initial line of text at the top of the page. It was only after checking the browser's activity indicator to see if it was still loading the page, it wasn't, that I started looking at more of the page and finally found the Next button at the very bottom of the page.\nShould it be all the way down there? No, not really. It should display near the end of the primary (in this case, the only) content on the page. Forcing navigational elements to the bottom of the page, not matter how much of the page's space is used by content, is a ridiculous use of the page's space. Imagine if this was an input form, and you've been typing away in the form's different input fields, but had to grab the mouse and drag it down to the absolute bottom of the page every time you wanted to move on to the next page in the wizard. This makes absolutely no sense. Don't do something like this in your forms.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Ridiculous IBM Password Form",
  "date":"Fri Mar 24 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1490400000,
  "url":"/posts/2017/ridiculous-ibm-password-form/",
  "content":"I needed to make some changes to my IBM newsletter subscription recently, so I clicked the ubiquitous Update Your Subscription link on the bottom of one of the newsletters. It had been a while since I logged in, so I had to go through the password reset process to get in. No worries, IBM had that covered, right? Yep, they sure did.\nWhen I clicked the “Reset My Password” link I received, I was presented with this form:\n\nFigure 1\nNow I know IBM cares about password security, and they'd force me to use some ridiculous, convoluted password character combination, but surprisingly the Create your new password form said ABSOLUTELY NOTHING about what those password requirements were.\nSigh.\nOK, this makes absolutely no sense. This is IBM, I know they produce security products, and offer consulting services to help their customers with security. They absolutely have to have some sort of requirements for my password, there's no way they wouldn't. But, the form, produced by a professional software developer I imagine, makes absolutely no reference to any requirements.\nOK, so I thought for a while, and came up with the perfect password to use. As I started typing, the form changed to what you see below.\n\nFigure 2\nAaaah, so IBM does care about password security, but chose to wait until AFTER I'd decided on a password to use before telling me what the password requirements are. This makes no sense – why wait until I've started typing a password to tell me what I need to include in my password? That is never a good idea. Statistically, there's limited chance I'm going to get this right without knowing what the password requirements are, so what this means is that EVERY SINGLE USER who uses this form will have to correct their chosen password upon receiving this previously hidden information. Ugh!\nInstead of letting users know in advance what the password requirements are, and allowing the user to pick their password with all the information they need at hand, IBM choses to let the majority of their visitors (a small percentage, a very small percentage, will get it right anyway) select a password that won't comply with the requirements before even telling them what the requirements are.\nNow do you see why this is a Stupid Developer Trick (SDT)?\nI've said this before, and apparently will continue to need to do so, respect your users and give them ALL OF THE INFORMATION THEY NEED before they need it, not after they need it. That's the minimum any of us should expect from any input form.\nOK, so now I know I need an 8 character password, so I'm good, right?\nNope, there's another warning as well that I can't figure out. It's possible the form is telling me that I can't use a previous password, but that's not guaranteed since the message is vague. Is it warning me that I shouldn't use a previous password or telling me that I can't use a previous password? Also, when it tells me not to use another password, is that another password I used previously on this site? Or another password I've used anywhere else at any time? I can't tell, can you?\nWell, at this point, I'm going to wing it and start to enter the password I've picked for myself. As I type this password, the form changes yet again. Only now does it have more password requirement information for me.\n\nFigure 3\nSo, apparently you have to keep adjusting the password you want to use as the password continues to provide pertinent information as you type. You've got to kidding me – does IBM hate its customers?\nFinally, after poking and prodding at the password, changing what I'm planning to use every time the password form gave me additional information about the password requirements, I was eventually able to enter an acceptable password.\n\nFigure 4\nWhat an absolutely horrible experience. Now, it could have been worse, but as password forms go, this is pretty horrible. You know what's the funniest part of this? Developers, as you work on implementing password forms, or any other type of form, be sure to give the user all of the information they need to accurately populate the form. Don't wait for them to make an error to tell them what they need to fill out your form. Tell them right up front. Identify all required fields, show input field patterns when they exist (like phone number, date or credit card) and treat them like you like them, not like you consider how to fill out the form to be a mystery.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Driving a Relay Board from Python Using GPIO Zero",
  "date":"Fri Mar 24 2017 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1490400000,
  "url":"/posts/2017/driving-a-relay-board-from-python-using-gpio-zero/",
  "content":"As you may have noticed, I've been working on a few projects lately that use relays. A while back, I bought some single, double and quad relay boards from yourduino.com (in China, I think). They were pretty inexpensive and I thought they'd work well for some of my projects. I never got around to using them – mostly because there were some jumpers on the board and no instructions and I really didn't have the patience to figure out how they worked.\nAnyway I got this cool Paddle Breakout HAT from ModMyPi, so I had an easy way to wire up the Pi to the relay board. I connected the relay board to the Pi's 5V output, Ground, and GPIO pin 18 then wrote a simple app to test it out. It worked! First try. Here's a picture of the setup, the board on the left is the relay testing jig I wrote about here.\n\nI created a GitHub Gist with the code, you can find that here in an easily digestible format: https://gist.github.com/johnwargo/ea5edc8516b24e0658784ae116628277.\nThe code uses the GPIO Zero library to interact with the relay board. You basically define an output device using the following code:\n\nThen, you turn the relay on by executing:\n\nAnd turn the relay off by executing:\n\nIt couldn't be simpler. Toggling the relay is easy too, just make a call to:\n\nThe GPIO Zero library takes care of tracking relay status automatically.\nThe relay board comes configured by default to trigger the relay when the input voltage goes low, so that's why the output device initialization includes the active_high=False parameter. The initial_value=False simply makes sure the relay starts in an off status.\nHere's the complete source code listing for the app:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Tim the Enchanter",
  "date":"Tue Mar 07 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1488931200,
  "url":"/posts/2017/tim-the-enchanter/",
  "content":"Through my kids, I recently met another couple and quickly realized we had a lot in common. The bromance started when I mentioned a quote out of Monty Python, and my new friend Tim, I call him Tim the Enchanter for obvious reasons, quickly responded with another quote. My wife quickly rolled her eyes, but I knew I had definitely had a new friend.\nFast forward a few months and I was sitting in my bedroom reading a book when my wife grabbed me and dragged me to the front door. Apparently she 'saw some movement outside' and I had to 'check it out'. Anyway, I grab a firearm (just kidding) fling open the door, and what do I find? This, full of gifts:\n\nTim and his family reproduced the Trojan rabbit from Monty Python and the Holy Grail and left it on my front porch filled with presents. Inside was a Ministry of Silly Walks wrist watch, a Monty Python coffee mug, and a Legendary Black Beast of Aaargh hat. What fun!\nI wore the hat for Halloween, sitting on the front yard distributing candy. The mug? I use it all the time.\nSo I had to figure out what to do with the rabbit. I couldn't throw it away, it's too cool. I couldn't store it a it would get ruined over time. The solution? Re-gift it. I figured that sometime in the future, I'd want to give Tim something, and I did. A few months later, I filled it with gifts and left it on his front porch for him to discover again.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Raspberry Pi Relay Controller",
  "date":"Mon Mar 06 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1488844800,
  "url":"/posts/2017/raspberry-pi-relay-controller/",
  "content":"A while back, I built a Python library for the Seeed Studio Raspberry Pi Relay Controller board; I wrote about that project on this site. As I worked to add some new features to the library, I realized that I needed an easy way to test the different components of the library. I decided to build a web application for the Raspberry Pi that provided an interface for each of the library's functions. I built the application using Flask, an easy to use micro framework for Python; you can find the project's complete source code at https://github.com/johnwargo/Raspberry-Pi-Relay-Controller-Seeed.\nWhen you install the application and configure the Pi to execute the project's server task at startup, you can point your Pi browser to http://127.0.0.1:5000 and you'll see the following interface:\n\nFigure 1\nHere, you can turn each relay on or off, toggle the relay's status and view the current status of the relay by clicking the buttons on the page. The All buttons (All On, All Off, and Toggle All) perform the specified operation on all of the relays simultaneously.\nFor example, you can flip a set of relays easily using the Toggle All button. Turn two of the relays on (say, 1 and 3 for example), then click Toggle All to flip them all, turning 1 and 3 off while turning 2 and 4 on.\nTo access the web application from outside of your Pi, you'll have to first determine the Pi's IP address. Open a terminal window and execute the following command:\n\nThe Pi will display network configuration settings for each of the device's network interfaces. If you're running the Pi on a wired network connection, then you would use the inet addr highlighted in the following figure. If using a Wi-Fi network interface, then you'll want the address for the wlan0 interface.\n\nFigure 2\nWith that address in hand, simply use it to access the controller. Open the browser on any local network connected device and use the address, plus the port number as the page address. For example, for my configuration shown above, I would use the following:\n\nThe web application uses Bootstrap, so it will automatically render correctly on any size screen. For example, the following figure shows the same web application running on my Nexus 7 tablet.\n\nWith this controller, you can connect different circuits to the relay board and flip them on and off as you validate your hardware. Then, when everything's working as expected, you can code your own application logic for the Pi, replacing this generic controller for your actual application code. Enjoy!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Using the Seeed Studio Raspberry Pi Relay Board",
  "date":"Tue Feb 14 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1487116800,
  "url":"/posts/2017/using-the-seeed-studio-raspberry-pi-relay-board/",
  "content":"I had an idea for a project, a Raspberry Pi-based power controller for my media center. I searched around for relay boards, and discovered the Seeed Studio Raspberry Pi Relay Board v1.0 https://seeedstudio.com/Raspberry-Pi-Relay-Board-v1.0-p-2409.html, so I thought I'd give it a try.\nNote: At the time, this was the only directly-mountable relay board I could find for the Raspberry Pi. Since then, I found another one in the ModMyPi PiOT Relay Board (https://modmypi.com/raspberry-pi/breakout-boards/modmypi/modmypi-piot-relay-board). I'll play with that one soon and publish my findings here; stay tuned.\nWhen I finally got around to playing with the hardware, I used (or should I say tried to use) Seeed Studio's Wiki Page for the board (https://wiki.seeed.cc/Raspberry_Pi_Relay_Board_v1.0/) to guide my efforts. Unfortunately, I quickly learned that the article was incomplete and didn't have everything I needed to work with the board. I mounted the board on my Raspberry Pi, powered it up, ran their sample test application, and got nowhere. It simply didn't work.\nI sent Seeed Studios an email asking for help and posted a couple of questions on their community forums, but had to wait more than a month to get a response. When I finally did hear back, it was to let me know that they were on vacation and it would be an even longer wait for help. Sigh. Finally, they contacted me and offered to help.\nAfter another week of sending them screen shots, I finally got useful information and was able to get the board operational. The purpose of this article (and associated Github repository at https://github.com/johnwargo/Seed-Studio-Relay-Board) is to show you how to use the board so you'll avoid the issues I had.\nUpdate: After publishing this article, I shared this information with the folks at Seeed Studio. They then updated their Wiki article with information directly copied from this article and the associated GitHub repository readme file. So, you'll finally find good, useful information on their product Wiki page - because I wrote it.\nIn the Github repository, I shared the code Seeed provides to test the board (so that you can grab it using git rather than copying and pasting it from a Wiki page) plus a Python module (and associated test application) you can leverage to use the relay board in your own Raspberry Pi projects. I also created a complete Raspberry Pi relay controller application (using Python and Flask); I'll publish information about that soon.\nThe steps for installing the board and verifying that it works includes the following steps:\n\nMount the Relay board on the Raspberry Pi\nEnable the Raspbian I2C software interface\nValidate that the Raspberry Pi recognizes the board\nRun some Python code to exercise the board\n\nIn the rest of this article, I'll show you how to do all of those things.\nMounting the Relay Board\nMounting the board is easy, it comes with the appropriate female headers you need to mount it on any Raspberry Pi board with male headers. Note: You'll have to add male headers to the Raspberry Pi Zero to use the board.\nSeeed Studio recommends putting some electrical tape on top of the Raspberry Pi Ethernet port before mounting the board. If you mount the board without using standoffs (as I've done in the example figure below), there's a chance the board will make contact with the Ethernet port housing and cause a problem.\n\nFigure 1\nFor a production project, I'd definitely recommend using standoffs to hold the two boards in place.\nThe relay board is configured for an older Raspberry Pi with a 26 pin header, so when you connected it to a Raspberry Pi with 40 pin headers, you'll need to shift it all the way to the side like I've shown in the figure. If you don't align the pins correctly, you'll have problems later as it simply won't work.\nEnabling I2C\nThe relay board communicates with the Raspberry Pi through an I2C interface (https://en.wikipedia.org/wiki/I%C2%B2C). This interface is disabled by default in the Pi's Raspbian OS, so you'll have to turn it on before you can use the board. Power up the Pi and let it boot to the graphical interface. When it's up and running, open the Pi menu, select Preferences, then Raspberry Pi Configuration as shown in the following figure:\n\nFigure 2\nIn the window that opens, select the Interfaces tab as shown in the following figure. Enable the option next to I2C as shown in the figure and click the OK button to continue. When you reboot the PC, the Pi should see the relay board. In the next section, we'll verify that the Pi sees the relay board.\n\nFigure 3\nValidating the Raspberry Pi Sees the Relay Board\nWith the I2C interface enabled, it's time to make sure the Raspberry Pi sees the relay board. Open a terminal window on the Pi and execute the following command:\n\nThe application will display a dump of the recognized I2C devices as shown in the following figure. In this example, there's only one I2C board on the system, the relay board configured at an address of 20. Yo",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "A Site In Transition",
  "date":"Sat Jan 28 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1485648000,
  "url":"/posts/2017/a-site-in-transition/",
  "content":"It's been a while since I've made major updates to this site. I picked this site's current template years ago, and it's served me well. However, I opened the site on my mobile phone the other day and Chrome on my Android device popped up a notice offering to display the site in a mobile friendly way for me.\nUm, huh? I thought the template I was using was mobile friendly. Nope, not so much.\nAnyway, so I've decided to update the template to something more…flexible. I've picked one, and thrown it up here, but I may change it, and I definitely have some cleaning up to do to make it look better. So, in the meantime, you'll be able to view the content more easily on any device and over time you'll see it tightened up and well suited for any browser. Please be patient with me.\nI'd been having an issue with page navigation, but a template switch made that problem go away. Bonus.\nWhen I first started this site, I used an existing Joomla! plugin to manage formatting my code listings. That plugin wasn't updated over the years, and I've not yet selected a replacement. One of the things I'm going to be doing as I update this site is fixing that and pulling out all the old code formatting stuff. As I do this, code listings may be kinda ugly. I'm sorry, but I'll fix this as soon as I can.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Faulty Amazon Purchase Review Process",
  "date":"Sat Jan 21 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1485043200,
  "url":"/posts/2017/faulty-amazon-purchase-review-process/",
  "content":"I've been doing a lot of IoT projects lately; both for work and for personal growth (fun). I want to be a bit more structured in how I secure microcontroller boards, so I've been picking up different packs of spacers, standoffs, screws and so on. I was working on a project where I needed M2 standoffs, so I hopped on Amazon to see if they had something I could use. I found a promising collection of standoffs, screws and nuts in https://amazon.com/gp/product/B013ZWM1F6. I ordered it and it quickly arrived at my door (who doesn't love Amazon Prime?).\n\nAnyway, when I opened it, I found a product that was professionally and securely packaged. The contents therein were of reasonable quality, so I was pretty pleased with my purchase. As I started looking at it, I noticed that there was a disproportionate number of screws and nuts to posts and sockets. In other words, as you started to work through this kit, you'd quickly run out of screws and nuts, leaving standoffs that you can't use for lack of connectors.\nAnyway, I decided to write a review; first to let people know this appeared to be a quality product, and second to let them know it has a critical flaw. Being an experienced writer, I fired up Microsoft Word and got to work; my fingers quickly spat out the following\nA great product and well packaged. The two containers came neatly packaged in a bag, each container has a solid clasp that should last the life of the product. The containers were taped shut, so there was little chance of everything falling out during shipment. Inside is a well-produced piece of paper listing the contents of each compartment. Well done.\nHowever, whoever created this kit didn't take into account how it would be used. The kit is woefully short on the number of screws and nuts you'll need to make full use of the product. No matter what happens, you're going to be heading out to buy more nuts and screws. Here's an example: the kit comes with 40 M2 male-female standoffs. To use these individually, as I plan to, you're going to need 40 screws and 40 nuts. The kit only ships with 20 of each. That doesn't make sense to me. There should be enough screws and nuts to accommodate all of the standoffs, not only half of them.\nI fired up my trusty browser and submitted this as a product review thinking it would be quickly published. Nope, not so much. A few minutes later, I received the following email:\n\nHere's the text so you'll be able to read it:\n&quot;Your review could not be posted.\nThanks for submitting a customer review on Amazon. Your review could not be posted to the website in its current form. While we appreciate your time and comments, reviews must adhere to the following guidelines: https://amazon.com/review-guidelines.\nWe encourage you to revise your review and submit it again. A few common issues to keep in mind:\n\nYour review should focus on specific features of the product and your experience with it. Feedback on the seller or your shipment experience should be provided at amazon.com/feedback.\nWe do not allow profane or obscene content. This applies to adult products too.\nAdvertisements, promotional material or repeated posts that make the same point excessively are considered spam.\nPlease do not include URLs external to Amazon or personally identifiable content in your review.&quot;\n\nHmmm, that surprised me as I did focus on specific features (its nuts and screws) and my experience with it. I did not submit any obscene content, did not advertise anything or include any external links. I should be good, right?\nThinking that they didn't like my comment about the person who created this kit. I thought perhaps that they didn't like me singling out the producer of this kit. I didn't mean the person who actually assembled the kit, but instead, the person who created it as a commercial product. So, using their submission guidelines as, well, a guide, I adjusted my content to remove the only content I considered to be even slightly offensive and resubmitted it:\nA great product and well packaged. The two containers came neatly packaged in a bag, each container has a solid clasp that should last the life of the product. The containers were taped shut, so there was little chance of everything falling out during shipment. Inside is a well-produced piece of paper listing the contents of each compartment. Well done.\nHowever, whoever assembled this kit wasn't paying much attention to how this will be used. The package is woefully short on the number of screws and nuts you'll need to make full use of the product. No matter what happens, you're going to be heading out to buy more nuts and screws. Here's an example: the kit comes with 40 M2 male-female standoffs. To use these individually, as I plan to, you're going to need 40 screws and 40 nuts. The kit only ships with 20 of each. That doesn't make sense to me. There should be enough screws and nuts to accommodate all of the standoffs, not only half of them.\nNothing, crickets. Completely ignored ",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Epic UX Failure at Bandsintown",
  "date":"Sat Jan 21 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1485043200,
  "url":"/posts/2017/epic-ux-failure-at-bandsintown/",
  "content":"I'm a HUGE music fan, in my car, in the house, or when I'm working, there's always music playing. Having formerly lived near Cleveland, OH, I'm also a big concertgoer and see as many shows as I can. A while back, I signed up for Bandsintown as a way to know when the bands I'm interested in are going to be performing nearby. I don't use the app much, but I have used it to highlight the bands I like. Recently, I've started getting emails like the following:\n\nFigure 1: Useless Bandsintown Email\nWhen I saw this, I immediately said: “Oh, I wonder what Beth has to announce.” I'd be much happier if they'd just include the message content in the email to me – after all, why send me a message letting me know I have a message and NOT include the message in the message? That makes absolutely no sense and already Bandsintown is delivering a poor user experience UX.\nSo, I clicked the link to see what Beth had to say and was presented with the following web page:\n\nFigure 2: Useless Bandsintown Web Page\nApparently I don't get to know what Beth has to say unless I fire up the app and see what her message is. I'm not going to do that. They've lost me as a user.\nWhat happened is they they've completely ignored the fact that I might check my email on my PC. In this case, I was. There's no reason to send me to an app, when the medium they're already using supports properly rendering the message. Even if they did want to send me to the app, which would have been an important piece of information to share with me in the original email message, they wait until I click the link and open a browser window before telling me that I can only read the message from the app.\nAt this point, they lost me as a user since they clearly don't care about me.\nWhy do they feel the need to force me to use their app? By including Beth's message in the email, they're reinforcing their service in my mind, and increasing the chance that I'll reopen their app. When I'm using my desktop PC to read my mail, there's no way I'm switching to a smaller device with a smaller screen to read this message.\nMy point here is that when you're developing a marketing campaign or implementing features into your service, you have to pay attention to how people will use it as well as what they'll be doing when they use it. In this case, they've made a faulty decision to assume everyone will be getting this email on their mobile device.\nNow, the last time I got one of these messages on my mobile device, I clicked on it, and the mobile app dutifully opened (as expected), but I wasn't taken to the message. Instead the app opened and I found no way that I could actually read the message from the band. Sigh. What a waste of a good opportunity to connect me with one of my favorite bands.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Arduino Twinkle Lights",
  "date":"Fri Jan 13 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1484352000,
  "url":"/posts/2017/arduino-twinkle-lights/",
  "content":"This project is an Arduino variant of the Pimoroni Firefly Light (https://learn.pimoroni.com/tutorial/sandyj/firefly-light) project. Basically you place two strings of battery-powered LEDs into a glass jar and use a microcontroller to fade one strand up while the other strand fades down. The fade up/down process repeats for as long as the microcontroller has power. You could even add 1 or more strands of lights to the project if you want.\nNote: removed outdated attachments November 11, 2022\nWhen I discovered the project, I thought it was really cool, but they threw a lot of hardware (a Raspberry Pi, two HATS and a battery) into the solution, so I wanted to see if I could build something with less parts and for less money. This version of project uses an Arduino compatible board (you could use most any Arduino for this project), a battery module and a battery. Here's a video of the white twinkle lights (https://vimeo.com/193441242) in action, and here's a Christmas version (https://vimeo.com/198351699) that uses Red and Green LEDs.\n\nFigure 1: White Twinkle Lights in a Jar\nYou can find the project's source code at https://github.com/johnwargo/Arduino-Twinkle-Lights. A PDF version of this article is available in the Attachments section (at the very bottom of the article).\nHardware Components\nThe project (as I've implemented it) uses the following required hardware:\n\nAdafruit Pro Trinket - 3V 12MHz (https://adafruit.com/products/2010).\nAdafruit Pro Trinket LiIon/LiPoly Backpack Add-On (https://adafruit.com/products/2124).\nLithium Ion Polymer Battery - 3.7v 500mAh (https://adafruit.com/products/1578).\nToggle switch; all you need is a SPST switch, but I used a SPDT switch I had lying around.\nA couple inches of 22 or 24 ga stranded wire.\n\nIf you chose to use a different microcontroller, you can replace the Adafruit Pro Trinket LiIon/LiPoly Backpack Add-On, which is purpose built for the Adafruit Pro Trinket, with the USB LiIon/LiPoly charger - v1.2 (https://adafruit.com/products/259).\nFor the white LED version, I used the following hardware:\n\nIkea ENSIDIG Glass Jar (https://ikea.com/us/en/catalog/products/10239888).\n2 Ikea SÄRDAL LED light chain with 12 lights (https://ikea.com/us/en/catalog/products/60277514).\n\nFor the Christmas version, I used the following hardware:\n\nSmall Mason jar\nWire Light LED Strand - 12 Green LEDs + Coin Cell Holder (https://adafruit.com/products/896).\nWire Light LED Strand - 12 Red LEDs + Coin Cell Holder (https://adafruit.com/products/897).\n\nThe LED strand is smaller for the Christmas version, so I used a smaller jar. A benefit of the mason jar is that you can mount the hardware to the underside of the lid, which makes it easier to turn on/off and charge.\nHardware Assembly\nStart by assembling the Adafruit Pro Trinket LiIon/LiPoly Backpack Add-On. To enable the use of a SPST switch to power on/off the board, cut the trace connecting the two holes highlighted in the following figure. This disconnects the board's power output, but once you connect a switch between those two holes, you'll be able to control power to the Trinket board.\n\nFigure 2: Adafruit Pro Trinket LiIon/LiPoly Backpack Add-On Board\nSolder the included headers to the Adafruit Pro Trinket LiIon/LiPoly Backpack Add-On. The header pins connect to the three holes in the lower-left corner of the board as shown in the previous figure. Insert the headers through the board from the bottom (the figure shows the board from a top view) and the black plastic part of the header is flush against the bottom of the board. The easiest way to do this is to insert the header pins in a breadboard, then mount the board on top for soldering as shown in the figure.\n\nFigure 3: Soldering the Header Pins to the Battery Charger\nCut two short lengths of wire, then strip the ends and solder an end of each wire to the switch.\n\nFigure 4: Battery Charger and Switch\nFinally, solder the open wire ends to the switch holes (highlighted in red in Figure 2). Since the hardware will be bumped around in the glass jar, I placed shrink tubing around the solder connections to protect them from being shorted out.\n\nFigure 5: Battery Charger Connected to the Switch\nSolder the Adafruit Pro Trinket LiIon/LiPoly Backpack Add-On onto the Arduino Pro Trinket 3V. The board mounts to the Battery, Ground and USB 5V pins shown in the upper-right corner of the board as shown in Figure 6.\n\nFigure 6: Adafruit Pro Trinket Pinouts\nTo protect the USB connector on the Trinket board, I placed a small piece of electrical tape on top of the board's USB connector. Figure 7 shows the completed board assembly.\n\nFigure 7: Completed Board Assembly\nNext, you'll need to disassemble the light strand units. Each comes with a battery pack and switch, but since we're driving them from the Trinket, you won't need those parts.\nFor the Adafruit color LEDs, use a Philips screwdriver to remove the screws from the battery case and open the case. The LED strand connects to the switch and battery contacts",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Code-locked Agents Do Not Get It",
  "date":"Thu Jan 05 2017 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1483660800,
  "url":"/posts/2017/code-locked-agents-don’t-get-it/",
  "content":"\nThis post copied from my World Without Apps site.\n\nI live in North Carolina, and there’s a big storm heading our way tonight. I knew we would be getting snow, but we’re all edge because we’re trying to figure out if we’ll have enough to do some sledding, but not too much that it’s not all gone in time for School on Monday.\nThis morning, I asked Alexa when we would get snow tonight, and she responded with:\n\nThere’s no snow in the forecast today for CITY_NAME, but there’s a Winter Storm Watch in effect between 7 PM tonight and 1:00 PM Saturday.\n\nWait a minute. We don’t have snow in the forecast, but there’s a winter storm watch in effect? Yeah, Alexa, I’m pretty sure that a Winter Storm INCLUDES snow.\nThat’s the problem with code-locked agents, they only know what they know, and Alexa apparently doesn’t know that snow’s a component of most every Winter Storm.\nWhen I asked Google Now the same question, she didn’t answer me, but did bring up a browser window with search results for the winter storm. At least she was able to relate “snow” with “weather and get me the answer I wanted. I asked the question verbally, I sure would have liked it if she answered me instead of giving me search results, but at least her answer was more direct than Alexa’s.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
  ]
  },

  {
  "title": "Amazon Cancel and Reorder",
  "date":"Sat Dec 31 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1483228800,
  "url":"/posts/2017/amazon-cancel-and-reorder/",
  "content":"If you've read enough articles on this blog, you probably know that I like to analyze application user interfaces. For Christmas, I ordered a copy of the Suicide Squad book for my son to give to my daughter, but later realized that my wife already had a copy. So, I dutifully hopped on amazon.com and cancelled the order. The order was in the process of being picked for shipment, so Amazon couldn't guarantee it would be cancelled, but what surprised me was the option they presented to enable me to order the product again. See the figure below:\n\nI laughed out loud when I saw it; was that really a use case? Someone was canceling an item only to reorder it? As I thought through the options, it just didn't seem to make sense. My thought was to write about the silliness of that option, but as I wrote this post, I realized that there were some valid cases for this approach. As the order is being processed, I can't change the credit card or the shipping address, my only option is to cancel the order (if I can) and place it again with the right options.\nSo, what looked like a stupid UI capability actually makes sense (although it took me quite some time to find the right reasons for the feature).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Tooling Changes",
  "date":"Sun Dec 18 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1482105600,
  "url":"/posts/2016/tooling-changes/",
  "content":"I've been doing some different work lately; building and writing about some IoT projects, writing some whitepapers, working on some documentation for Microsoft, and writing a bunch of code (Ionic, TypeScript, and more). I noticed that I've been spending a lot of time lately with some tools I've not used much lately. I thought I'd write about it here.\nMarkdown &amp; MarkdownPad\nAll of the IoT tutorial work I've done recently for AT&amp;T, and all of the documentation work I'm doing for Micosoft have been in markdown(https://daringfireball.net/projects/markdown/). I remember when I first encountered an .md file, it was in the readme files for the Apache Cordova team. I did some searching online and couldn't find anything about the file extension, so I had to ask the Cordova dev team what it was. I haven't found a good markdown editor on the Mac, but I'm a huge fan of MarkdownPad (https://markdownpad.com/) although it seems to have been abandoned by its author – the last update was in 2013. That's unfortunate as it's the best, and most professionally produced, markdown editor I've found for Windows.\nThe biggest requirement for me is to be able to view the markdown alongside the output, so I can clearly see how my work will be formatted online. MarkdownPad does this for me, other Windows editors I've used (Visual Studio Code, JetBrains WebStorm, and many others) simply don't do that.\nWhen I started working for AT&amp;T and Microsoft, it was the first time I'd worked with markdown files with embedded image files – I quickly learned that MarkdownPad doesn't deal with that very well – the two sides of the editor window (code and output) don't stay in sync when you're linking in images into your files. MarkdownPad is also not compatible with Windows 10, you have to install some extra software to get it to work, and even that's buggy. That's too bad, I wish Evan Wondrasek would update his app.\nGit\nI'd used git and github before, mostly for managing my own code and accessing others. My work at AT&amp;T and Microsoft have forced me to actively interact with others in multiple code repositories, so I've gotten more experience with it. I've even become a more frequent user of git integration in WebStorm, PyCharm, Visual Studio Code and more. I haven't yet had to recover from some shoddy coding, but integrating Git into my development workflow has made me more confident.\nVisual Studio Code\nI became a big fan of WebStorm when I learned it had Apache Cordova support, and I wrote a bunch of code using the IDE. I even adopted PyCharm (a Python IDE from the same codebase) when I taught myself Python this year. At Microsoft, I've started using Visual Studio Code for all of my typescript and Ionic coding. It's a really great IDE, and, with all of its available plugins, it's very capable. I want to use Visual Studio for my Ionic coding, mostly because of the testing and debugging capabilities Visual Studio Tools for Apache Cordova gives me, but the lack of a terminal window in Visual Studio forces me to leave Visual Studio to use the Ionic CLI to add pages, providers and so on. This isn't a big deal, and I expect I'll spend more time in Visual Studio than Visual Studio Code going foreword. I'm still pretty impressed with what Code provides, how often Microsoft updates it, and how many cool plugins are available. It's going to be fun to see what happens with this tool over the next 18 months.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Raspberry Pi Weather Station",
  "date":"Fri Dec 16 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1481932800,
  "url":"/posts/2016/raspberry-pi-weather-station/",
  "content":"A while back, I built a Raspberry Pi-based weather station. The hardware measures weather values (temperature, humidity and pressure) using the Astro Pi Sense HAT then uploads the data to a Weather Underground weather station. The Sense HAT board includes instruments that measure temperature, humidity and barometric pressure plus an 8x8 LED display, a joystick, and an accelerometer.\n\nThe HAT was created by the folks at Astro Pi; elementary school children were solicited to create experiments using the Sense HAT it that would be executed on the International Space Station. Eventually, many experiments were selected and an astronaut performed them and sent back the results for analysis. I read different articles about this board, so I decided to create a project using it. I'd wanted to install a weather station in my yard and upload the weather data to Weather Underground; the Sense HAT and a Raspberry Pi seemed like a great way to do this.\nI submitted the project to the folks at Make Magazine and they published it in the December 2016/January 2017 edition. You can find a the project in Collect and Display Weather Data with a Raspberry Pi. Enjoy!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Microsoft Cordova (TACO) Docs",
  "date":"Fri Dec 16 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1481932800,
  "url":"/posts/2016/microsoft-cordova-(taco)-docs/",
  "content":"You may have noticed that I've not been very active on this site for a while. Reason being is that I lost my job back in July and have been busy looking for work and doing freelance writing and contract work in the meantime. Please contact me if you'd like to hire me.\n\nI'm currently doing some work for Microsoft, working with the team that produced the Microsoft Visual Studio Tools for Apache Cordova (TACO). In the first part of my work, I updated all of the relevant Cordova documentation for Visual Studio 2017. You can find the published articles at https://taco.visualstudio.com. Specifically, I updated the following existing documents for the new version of Visual Studio, plus added some new ones:\n\nVisual Studio Tools for Apache Cordova (https://taco.visualstudio.com/en-us/docs/vs-taco-2017-intro/)\nInstalling Visual Studio Tools for Apache Cordova (https://taco.visualstudio.com/en-us/docs/vs-taco-2017-install/)\nGetting Started With Visual Studio Tools For Apache Cordova (https://taco.visualstudio.com/en-us/docs/vs-taco-2017-first-app/)\nRun Your App Using Cordova Simulate (https://taco.visualstudio.com/en-us/docs/vs-taco-2017-cordova-simulate/)\nVisual Studio Tools for Apache Cordova: Toolsets (https://taco.visualstudio.com/en-us/docs/vs-taco-2017-toolsets/)\nVisual Studio Tools for Apache Cordova: iOS Guide (https://taco.visualstudio.com/en-us/docs/vs-taco-2017-ios-guide/)\nMigrate a Cordova project to Visual Studio 2017 (https://taco.visualstudio.com/en-us/docs/vs-taco-2017-migration/)\nUsing TypeScript in a Cordova project (https://taco.visualstudio.com/en-us/docs/vs-taco-tutorial-typescript/)\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "AT&T IoT Starter Kit Getting Started Guide",
  "date":"Fri Dec 16 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1481932800,
  "url":"/posts/2016/at&t-iot-starter-kit-getting-started-guide/",
  "content":"During my between fulltime jobs lull this year, I did some freelance writing work for AT&amp;T. They created an interesting (and useful) IoT platform for developers to use to build their IoT projects.\n\nThe platform includes AT&amp;T Flow, a cloud-based application execution environment based on the IBM Node-Red open source project. It enables developers to build an execution environment for processing data from IoT applications. They also provide AT&amp;T M2X, a streaming data storage environment for IoT projects. The starter kit includes a programmable microcontroller board and a cellular shield (for cellular [mobile] network connectivity) and a sample application that exercises the boards and platform.\nMy job was to take an existing getting started guide and polish it up. I took the existing work and expanded it with more complete instructions and detailed descriptions of each component. You can find the finished whitepaper in: AT&amp;T IoT Starter Kit: Getting Started Guide.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Are Native Mobile Apps Doomed?",
  "date":"Wed Nov 16 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1479340800,
  "url":"/posts/2016/are-native-mobile-apps-doomed/",
  "content":"\nThis post copied from my World Without Apps site.\n\nYes, they are. But not for the reason most people think.\nI’ve been monitoring the press, looking for articles that spark topics for this blog, and I’m only now starting to see work that relates to this topic, but for the wrong reasons – hence this post.\nPundits and bloggers are starting to pick up on the fact that mobile apps are dead (or near death). Surprisingly, they’re making this announcement in response to advances in the mobile web browser, specifically progressive web apps. Don’t get me wrong, progressive web apps are interesting, and the use of them will have a big impact on user experience (while at the same time, simplifying development). Here are some examples:\n\nNative Apps are Doomed\nBrowsers, not apps, are the future of mobile\n\nMy argument here is that Agents, not apps, are the future of mobile. Apps are old news. So quaint, allowing me to do one thing, and hopefully do that one thing well when I can tie multiple systems together through agents and the WWA.\nWe lost the chance to have one, universal agent we could all tune to our needs when Samsung purchased Viv. All we have right now is islands of interaction (Alexa, Google Now, Siri, Viv, and so on) with code-locked solutions. What will it take to kick this up to the next level?\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
  ]
  },

  {
  "title": "Samsung Buys Viv",
  "date":"Thu Oct 06 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1475798400,
  "url":"/posts/2016/samsung-buys-viv/",
  "content":"\nThis post copied from my World Without Apps site.\n\nI checked my inbox this morning and found some amazing news. Apparently Samsung has purchased Viv; you can read the Samsung press announcement. The reason I see this as amazing news is that it’s something that I never expected would happen. I met with Viv’s founders a little less than a year ago, before their public demo, and they assured me that they felt that Viv would be the last jobs they ever had.\nMore importantly, this acquisition is going to have a huge, negative impact on the effectiveness and overall reach of Viv.\nAs I listened to Viv’s founders discuss what they were making, it was clear to me that in order for them to be successful, they couldn’t let themselves be bought by anyone. I imagine with certainty that both Apple and Google made attempts to acquire Viv, but to join either of those companies would limit their ability to be the ‘Global AI’ they said they wanted to be.\nAs I’ve written before, the issue I have with Alexa, Cortana, Google Now (now Google Assistant), and Siri is that these solutions are code-locked, they can only do what they’re directly coded to do. Each solution gets a little bit of flexibility from leveraging search to create a response when they don’t have a pre-coded solution to a problem, but at the end of the day, any interesting transactions ANY of those solutions deliver, only happen because someone has coded the transaction.\nGoogle Assistant, demonstrated this week by Google, is a little better than the other solutions in that it maintains some context, a short term memory of recent interactions or direct access to the smartphone screen, to help it deliver more interesting results.\nViv, on the other hand, delivers transactions, any kind of transaction, because it knows what you want and it knows what it knows and can stitch it all together, no matter how complex, to deliver the goods. That is, well, was, a game changer for me.\nNot anymore.\nI understand why Samsung wanted Viv; they want to create the best interactive consumer devices, and owning Viv is a great way to do that. Unfortunately, with Viv as an independent entity, Viv’s capabilities would have been available ANYWHERE. Your car, office, smartphone, garage door opener, newspaper box, and more could all have had intelligence added to them by leveraging Viv. At the same time, you’d also see Google, Apple, Microsoft all license Viv to add an extra layer of interaction to their services. Companies and third party developers would augment Viv’s AI; it would be made available through devices and services all over the world and you’d only have one system to learn, one set of preferences to manage, and universal access to everything.\nNot anymore.\nViv’s sale to Samsung will take them out of the market and you’ll only find Viv’s capabilities in Samsung devices and the limited subset of device manufacturers who license the technology.\nThe quality of your dynamically assembled experiences will vary depending on whether you’re working with Google Assistant, Alexa, Cortana, or Siri. You’ll have to learn the command interfaces of each, deal with voice recognition idiosyncrasies of each, and won’t be able to stitch together actions based on previous activities if they were done through different services. You definitely won’t have a single set of preferences you can manage, you’ll have to train each service to understand your specific needs. Sigh.\nIt’s interesting for Dag and the other folks at Viv - once again, they build a company and sell it before ever really going to market. It doesn’t suck to be them.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Natural Language Processing"
  
  ]
  },

  {
  "title": "Raspberry Pi Reminder Project",
  "date":"Wed Sep 28 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1475107200,
  "url":"/posts/2016/raspberry-pi-reminder-project/",
  "content":"Note: this article was originally published as Get a Flashing Meeting Reminder with a Raspberry Pi online at Make Magazine.\nIntroduction\nI work at home and I spend a lot of time on the phone talking to clients and vendors. My employer uses Google Apps (which includes Google Calendar and Gmail) and the appointment notification capabilities of both are not very robust. Well, they're robust, but not enough to get my attention when I'm distracted. What I find is that I often miss the notification when I'm busy doing something else or I notice the notification, but quickly forget about just a few minutes later and ultimately miss some meetings or join late.\nOne day, after being 15 minutes for a meeting, I decided I had to fix this problem. I needed a more effective way to alert myself of upcoming appointments. As I spend a lot of time on the phone, I didn't want an audible alert, so I decided I'd do something visual. While browsing the Adafruit web site, I noticed the Pimoroni Unicorn HAT (https://shop.pimoroni.com/products/unicorn-hat) and that had me thinking of solution. The Unicorn HAT is an add-on board for the Raspberry Pi that consists of an 8x8 array (that's 64 total if you're counting) of bright RGB LEDs. What if I wrote a Raspberry Pi application that connected to Google Calendar and checked my calendar for my next appointment then flashed those 64 LEDs to let me know? As long as I was awake and in the room, I'd likely see the alert and decrease my chances of missing an appointment.\nWell, that's what I did and I'll show you how to do it too. You can see the final project in action at https://youtu.be/X111pAaEP-k.\nI ordered a Unicorn HAT then grabbed a Pi I had lying around and started writing code. The app for this project is written in Python, and is the first Python code I've written, so be gentle with me; you can find the code at https://github.com/johnwargo/pi-remind. The code checks the calendar every minute for appointments that start within the next 10 minutes. If there's an appointment starting between 10 and 5 minutes from now, the lights will all flash white for a second or so. Between 5 and 2 minutes, the lights will all flash yellow twice. At less than two minutes until the appointment start, the lights will swirl in a multi-color splash. I'll describe how to more interesting things with the lights at the end of the article.\nThe hardware for the project is pretty simple, all you need is a Pi, the Unicorn HAT, a power supply and a case for the Pi. You should be able to acquire the parts for less than $70US and assemble it all in just a few minutes.\nComponents\nFor this project, I used the following components:\n\nRaspberry Pi. The Pimoroni Unicorn HAT supports Raspberry Pi models 3, 2, B+, and A+, so you'll have to pick one of them. For this project I used a Raspberry Pi 2 Model B.\nMicro SD memory card (4 GB or higher) to hold Raspbian, the Raspberry Pi OS (https://raspberrypi.org/downloads/raspbian).\nPimoroni Unicorn HAT. I purchased mine from Adafruit (https://adafruit.com/products/2288).\nRaspberry Pi Power Supply. Any Pi compatible power supply will work, I used the CanaKit 5V 2.5A Raspberry Pi 3 Power Supply / Adapter / Charger (https://amazon.com/CanaKit-Raspberry-Supply-Adapter-Charger/dp/B00MARDJZ4).\nRaspberry Pi case. Again, you can use whatever case you want, I selected the Adafruit Raspberry Pi B+ / Pi 2 / Pi 3 Case - Smoke Base - w/ Clear Top (https://adafruit.com/products/2258). I picked this one because it had a clear front, so the lights would show clearly even with the top on, and because it looked cool.\n\nAssembling the Hardware\nFigure 1 shows the parts I used for this project (minus the power supply). The Unicorn HAT on the left is facing down so you can easily see the female headers on the back of the board that match the male Pi's GPIO headers.\n\nFigure 1 – Project Parts Ready For Assembly\nFlip the Unicorn HAT over and align the GPIO Pins with the female header socket on the HAT as shown in Figure 2\n\nFigure 2 – Unicorn HAT Connected to the Raspberry Pi\nWith the HAT properly positioned, push down gently to seat the board securely on the Raspberry Pi as shown in Figure 3.\n\nFigure 3 – Completed HAT installation\nRight now, the HAT is floating free over the Pi, connected only through the header pins. Since the whole contraption will be sealed in a case, I didn't feel the need to mount the HAT any more securely, but you may want to. Adafruit sells a set of spacers (https://adafruit.com/products/2336) you can use to secure the other side of the HAT against the Pi.\nNext, install the Pi and HAT in the case as shown in Figure 4, then attach the cover (not shown).\n\nFigure 4 – Installing the Project Components in the Case\nAt this point, the hardware is all installed and ready to go. When finished, the Pi will only need network and power connections, but for the remainder of the setup process, you're going to need a display (monitor), keyboard, and mouse. Connect those components to the Pi ",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "All Things Open 2016",
  "date":"Sun Sep 25 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1474848000,
  "url":"/posts/2016/all-things-open-2016/",
  "content":"I recently accepted an invitation to speak at the All Things Open conference in Raleigh on October 26 and 27. I presented at the conference last year and I really enjoyed the event; lots of interesting topics, lots of interesting people. I delivered a session on Apache Cordova and got to spend some time with other Cordova enthusiasts like my colleague Carlos Santana (NOT the guitarist you're thinking of).\nThis year, I'm still talking about Apache Cordova, but I'm also going to spend some time talking about JavaScript-driven Native frameworks like NativeScript and React native plus Microsoft's Xamarin platform. Here's my abstract for this year's talk:\n&quot;There's a lot of ways to deliver mobile apps: native, web, commercial mobile app development platforms, and more. In between those options are popular open source projects that provide robust, alternative approaches. In this session, you'll learn about the venerable Apache Cordova project, the project that defined the hybrid mobile development approach, plus new upstarts like Telerik's NativeScript, Facebook's React Native and Microsoft's Xamarin that take hybrid to the next level, giving developers the ability to create compelling, performant native apps using JavaScript or other languages. Expect a fast-paced, high-energy session with lots of content as John Wargo introduces you to a different way to do mobile using open source tools.&quot;\nI look forward to seeing you there!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "FatCow Fail",
  "date":"Wed Sep 21 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1474502400,
  "url":"/posts/2016/fatcow-fail/",
  "content":"I'm about done with FatCow. As you may know, I've been a big fan of FatCow and many, many years now. I've been a customer for about 15 years and have been recommending their service to anyone I know who needs to host email or web sites. I have multiple accounts with them and even pay an extra fee every month to get higher level support – mostly just so I could give them more money since I think (thought) they provided such a great product.\nSo, what happened?\nFalse Positive\nWell, in order to better protect their customers' sites and to help generate additional sales for their SiteLock product offering, FatCow has started performing periodic, free security scans. What's weird is that they're selling SiteLock, but not using SiteLock for the scans. The issue for me is that scanner repeatedly kicks out false positives and its driving me crazy.\nLet me give you some examples.\nEvery week or so, I receive the same email from the FatCow Security team:\n&quot;During a routine scan, the security team at FatCow discovered infected files in your &quot;account_name&quot; account. Typically, these security vulnerabilities are due to the presence of an outdated application or script in your account.\nYou can view a list of the infected files in the /stats directory of your account, in a file named 'websitescan.txt.' You can find more information on how to access this file, interpret its contents, and remove infected files in the article below: https://fatcow.com/knowledgebase/beta/article.bml?ArticleID=437.\nPlease make sure to check any file backup(s) you have for a clean copy of the infected files. If you have clean copies, you can upload those. If not, once you get the infected files cleaned or removed, we recommend you keep regular backups of your website going forward\nHowever, If you don't feel comfortable removing the infected files yourself, or would like to talk to a security expert, we recommend that you contact our preferred partner, SiteLock. You can find out about their security solutions at https://fatcow.com/product/sitelock, or call them directly at 1-855-378-6200.\nFinally, to learn more about how to keep your site safe, visit the article below: https://fatcow.com/knowledgebase/beta/article.bml?ArticleID=2324#Nugget_5264 .\nSincerely,\nThe FatCow Team&quot;\nThat's cool, right? Proactive scanning of my site coupled with providing me with all sorts of information about what this means and how to fix it. So, I quickly jumped on my site and looked at the file; here's the contents:\n\nThe infected file? It's a log file created by the Akeeba Admin Tools plugin. I use this tool on my Joomla sites to block attacks and, when it recognizes an attack, it blocks the IP address of the attacker then logs the activity to a log file.\nThat's not an infected file, it's a file containing information describing a thwarted attack, a false positive. So, I'm regularly pestered with these alarming emails telling me my site's infected when it's actually not. I want them scanning my site and I'm actually paying for the SiteLock service on most of my accounts, but it's really not doing much good for me right now.\nI've also gotten these infected file notifications on FatCow's server-generated system log files. They send me a notice telling me to clean up these 'infected' files when the files in question are being generated directly by the server, not by anything I'm running. My simple CMS-based sites don't even have access to the folder where these system generated log files are placed, but they're still marking them as being infected when they're not.\nSo, I told the folks at FatCow that they're getting false positives and I get the following response:\n&quot;Hello,\nThank you for your reply.\nYou have received the message from sitelock saying there are infected files in the account. If you have removed the infected files from the account and if you wish to scan the account again, please let us know. With authentication to the account: You can provide us the authentication of the account by answering security question set in the account: Question removed for security? You can check the security answer by going to: https://fatcow.com/secureControl/security-question.html?pid=4059212 .\nAlso, we have given below some suggestions to safeguard your website:\n\ngenerate a strong password combination for account, FTP, database and mailboxes.\nscan local computer with good antivirus, antispyware programs and clean bad programs.\nkeep the software up-to-date with vendors/developers, and seek their support/forums for any known vulnerabilities/fixes/workarounds available.\nupgrade all the applications in your account to the latest version – this also applies to plugins, themes, modules, etc.\n\nIf you have any further questions, please feel free to contact us, We are available 24x7.&quot;\nSo, I' haven't removed anything from the site as there's no infected files but let them know about the issue and all the FatCow security team can think of is to let me know that I",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Autostart Python App on Raspberry Pi in a Terminal Window",
  "date":"Mon Aug 22 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1471910400,
  "url":"/posts/2016/autostart-python-app-on-raspberry-pi-in-a-terminal-window/",
  "content":"I've coded a few Raspberry Pi Python projects recently that need to execute when the device boots:\n\nRaspberry Pi Weather Station\nRaspberry Pi Reminder App\n\nAs these apps throw status and diagnostic information out to the console as they run, I wanted to be able to run the applications in a terminal window once the Pi boots. I poked and prodded at Google search results and found a couple of solutions, but, until recently, none of them worked quite right for me. I finally figured out why, so I thought I'd write about it here.\nOf the articles I found online, several had startup process running the app, but others started the app using a script file. Some Pi libraries need to execute with supervisor privileges, so I had to be careful of that as well. In order to easily accommodate that potential requirement, I decided to implement my solution using a script file.\nTo start, I created a simple script file that starts my Python app:\n\nNotice that for this app, it will only run under supervisor privileges, so I execute the python command using sudo. The python command happens to be in the /usr/bin/ folder, alongside sudo, so I didn't need to provide a full path to the python command in the bash script.\nBefore enabling auto startup, I'd probably better test the script first, right? Open a terminal window, navigate to the folder where the script is located and execute the following command:\n\nYou got a permission denied error message, right? That's the first fault point in this process, the bash script is solid, but the OS simply doesn't know it can execute it. So, before you can execute the bash script, you have to set its execution bit using the following:\n\nWith that in place, you should be able to execute the script from the terminal.\nNow on to the next potential problem. When I first crafted my app, I expected that I'd execute it directly from the app folder using:\n\nSo I didn't pay any special attention to how the app accessed local files. That creates a problem for auto startup. Let me give you an example.\nIn one of my apps, I opened the app's configuration file using the following code:\n\nThat worked wonderfully when executing my app from the folder where it resides. As soon as I tried to execute it from a startup script, it would fail miserably and NOT show me any indicators as to why it wasn't working. The solution? Test the script from another folder, like this:\n\nThe terminal window will remain open and you can view, and correct, any errors that appear. For my app, I had to replace the code anywhere where I tried to open a local file, and instead pass the complete path to the project folder like this:\n\nWith that script file in place, the script will execute from anywhere and I'm ready to go.\nI found two ways to execute my script that worked for me. The first is to create a .desktop file and copy it to ~/.config/autostart. For my use case, I called the file start-remind.desktop. Populate the file with the following information:\n\nWhen you reboot the system, the OS parses the .desktop file and loads the bash script.\nNote: the only lines, I think, you really need are the following:\n\nHere's where I learned this trick: https://raspberrypi.org/forums/viewtopic.php?f=91&amp;t=80096.\nThe next solution is a little easier and you can read about it here: https://raspberrypi-spy.co.uk/2014/05/how-to-autostart-apps-in-rasbian-lxde-desktop. All you have to do is add an entry into a specific file and it will run your bash script at startup. Open a terminal window and execute the following command:\n\nAdd the following lines to the end (bottom) of the file (you can see an example of this in the figure below):\n\nTo save your changes, press ctrl-o then press the Enter key. Next, press ctrl-x to exit the nano application. Reboot the Raspberry Pi. When it restarts, both python processes should execute in terminal window as expected.\nHere's an example from a project I'm working on that opens two windows:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Withings – Useless Input form",
  "date":"Sun Aug 21 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1471824000,
  "url":"/posts/2016/withings-useless-input-form/",
  "content":"I use the Withings (https://withings.com/us/en/) app to track my blood pressure and weight. I dropped a bunch of weight a few years ago and it helps me stay on track when I track it. My blood pressure has been wonky, so tracking that is a good thing as well. I'd like to get one of those scales and a Sphygmomanometer that automatically updates the app, but for now I'm doing it manually.\nEvery week or so, the Withings app sends me an email summary of my stats. In this morning's email, they offered me a chance to set a weight goal, and I quickly clicked on the link. After logging me in, I'm presented with the following form:\n\nAs you can see, it's asking me to set my goal (my desired weight). So, recognizing where my weight currently is, I decided that my goal should be 230 lbs. and I dutifully tried to enter that value. Apparently I can't do that.\nYou can't tell from the figure, but the input field is a spinner, with up and down arrows you can use to increase and decrease the value. For some bizarre reason, they've setup the form so those UI helpers disappear when the field loses focus. That's not helpful.\nThe form's asking me for my desired weight, and I'm trying to enter my desired weight, but it won't let me. I guess, I can't tell from any of the details on the form, they're asking me to enter a weight difference, not an actual weight target – but then how exactly is that a weight goal? By asking me for a weight difference, apparently I'm supposed to be entering a weight loss goal, not a weight goal. Sigh.\nNotice too that the input field allows me to spin to a negative number; apparently the developer of this form didn't know about the HTML input field 'min' attribute (https://w3schools.com/tags/att_input_min.asp) that would have allowed him (or her) to restrict the input to only positive numbers.\nNotice as well that I can only set a weight loss goal of 7 lbs. or greater. What if I only needed to lose 5 lbs., apparently I would not be able to set such a worthless goal using this form.\nInput forms must be designed so the form's user knows exactly what is expected of them. The form's content should be updated so it's clear I'm setting a weight loss goal, not a weight goal. The input field should have its min attribute set so, first of all, the user can't set a negative weight loss goal, and so any positive value is acceptable. It's all fine and dandy that you want me to set goals of 7 lbs. or more, perhaps I have more reasonable expectations and know I can only lose 4 lbs. by a specific date.\nIs the desired weight field required? You betcha it is. How about target date? Yep, that one is too. Do you see any visual indication that any of the fields on the form are required? That's another requirement – that users be able know clearly which fields they must populate to submit the form.\nAs I've proven, this form is completely useless and it was worth more effort than was needed for me to understand how to use the form. It's not rocket science folks, create input forms that are clear, succinct, well documented and easy to use. To do anything else is a waste of my time.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Semantic Web Services",
  "date":"Wed Aug 03 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1470268800,
  "url":"/posts/2016/semantic-web-services/",
  "content":"\nThis post copied from my World Without Apps site.\n\nWhen I first started thinking about the World Without Apps, I wasn’t thinking it would be a smartphone phenomenon; instead I imagined everything except the smartphone being the key to this revolution (my house, car, office and so on). I never expected smartphone processors to be able to handle the load or that cloud technologies would be so prevalent and so powerful that they could support things like Google Now and Apple’s Siri. How wrong I was - smartphones are core to this WWA revolution, and I’ll write more about that later.\nRegardless of how WWA is implemented, there’s a core piece of technology that enables it, the ability for web services to self-describe themselves to any consumer. As I mentioned in an earlier post, Amazon Alexa, Apple Siri, Google Now, and Microsoft’s Cortana are code-locked; they can only do things that they’re coded to do and nothing more. Now, these technologies have an out that enables them to handle most any request (at least most but Siri): when they can’t figure out what you’re asking them, they revert to delivering search results hoping you’ll find the answer you want there.\nHowever, sometimes search doesn’t work that well for consumers as shown in the following figure. In this example, I asked Siri how long it would take me to drive to the moon. A reasonable question, I thought; I was watching a special on the Apollo program and I was curious. Siri heard my question correctly as you can see from the figure (although she skipped adding a question mark for some reason), but even when correctly ascertaining the meaning of my words, she still didn’t get it and instead told me how long it would take me to drive to Howl at the Moon (I didn’t even know we had one of those locally).\n\nFor voice interaction to work (whether it’s through an app or some universal agent), the data aggregator (the agent) has to know how to know a lot of different things. It has to know things, and it has to know how it knows things or at least where to find things. I’m not talking about Watson playing Jeopardy, but some sort of universal agent that just, well, knows things.\nHow does it know what it knows? Semantic Web Services.\nWe have the Semantic HTML, technology that lets web pages self-describe itself so computers can divine information from the page more easily. In order for digital assistants, agents, or whatever you want to call these things to be able to do your bidding, they have to have a catalog capabilities available to them. That means that developers expose their capabilities through web services then describe them in such a way that multiple agent platforms can consume them when they need to.\nThe flaw of the Google Now, Siri, Cortana or Alexa approach is that there’s no way to augment a service’s capabilities without writing platform-specific code. Google Now, Siri and Cortana expect local apps to provide services, so to extend those services you’ll have to build an app and convince users to load it on their phones. You can extend Google search by publishing data in a way Google can easily consume, and therefore make your stuff available to Google Now, but that’s a hack and there’s no guarantee Google will use your data in the way you intended.\nAlexa and Viv on the other hand expose a cloud API developers can use to publish their capabilities to the service. Alexa enables developers to define what words they want used to invoke their service, and you can only consume your services when those specific words (or their variants) are uttered. Viv on the other hand is supposed to be exposing an SDK developers can use to describe their services and publish them to Viv. Once there, Viv can use them in any way she wants to deliver results to her users.\nThe way I look at this is that development organizations have to start thinking about how they’re going to expose their money making capabilities in a very generic way so that they can be consumed by ANYTHING. The web and mobile apps become core channels, ones that always need accommodation, but new channels, or at least new agent technologies, will pop up and demand attention. What we need to accommodate this is a standard definition of semantic web services, so developers can focus on only one way to easily expose their capabilities to the world. Instead of wrapping services in each vendor’s SDK, we need one common SDK that accommodates all. With this in place, there’s no limit to what the World Without Apps can accomplish.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Voice-enabled Agents Everywhere",
  "date":"Tue Aug 02 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1470182400,
  "url":"/posts/2016/voice-enabled-agents-everywhere/",
  "content":"\nThis post copied from my World Without Apps site.\n\nOne of the reasons I became so certain that we were entering the age of no apps is the rise of voice agents. My BlackBerry had voice control capabilities years ago and Android and iOS both added capabilities well. My 2007 car supported an option for voice control, but I never installed one. The precipice was when I purchased an Amazon Echo for the kitchen. I’d started using Google Now and Siri for things, random searches, phone calls and opening apps, but when the Echo came into the house, it changed music for me.\nI’m a huge fan of Sonos (www.sonos.com); I’ve got 4 of them in the house and I was expecting to add more before the Echo came to town. For a long time, I desired the ability to control my Sonos devices via voice control. I just wanted to be able to walk into a room and ask the device to start playing music. Sonos hasn’t adopted voice control, but as soon as I got an Echo, I found that I could play whatever music I wanted plus do more (such as check my calendar or put items on my todo list). What I quickly found was that I abandoned the Sonos device in the same room where I had an Echo since it was so much more work to open up an app to pick what to play when I could just ask for it. It didn’t matter that the Echo sound quality was lower than Sonos, the convenience factor so outweighed sound quality that the Sonos is now collecting dust. Apparently a lot of Sonos customers have made the same switch.\nThe biggest issue is that so many personal or household devices are adding voice control, that there’s so many devices listening to you at all times. I even have multiple Android devices, so when I say “OK Google” multiple devices answer. In my house, I have 6 Android devices, one iOS device, two Echo devices – all of which are constantly listening to us, waiting for the next command. We also have an Xbox as well as a couple of smart TVs, all of which are listening as well.\nSo, in this World Without Apps (WWA), apps are going away at the same time that devices that are listening to us, in order to help us, of course, are increasing. We’ll have voice-enabled agents everywhere, all vying for our attention. How exactly do we deal with that?\nWell, I imagine our cell phones become less important. With ubiquitous network connectivity and smart devices surrounding us, why do we need to carry a physical device around with us? I imagine that we’ll need access to screens in order to be able to interact with those data-driven apps I mentioned in an earlier post. Beyond that, you can interact with your surroundings without having a physical device in-hand. Initially, those agents will be able to communicate with you through a Bluetooth headset for example, but eventually, once embedded technology becomes prevalent, you’ll be able to have private interactions with these agents through the electronics embedded into your brain. How cool would that be?\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
    "Natural Language Processing"
  
  ]
  },

  {
  "title": "A World With Less Apps (WWLA)",
  "date":"Mon Aug 01 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1470096000,
  "url":"/posts/2016/a-world-with-less-apps-(wwla)/",
  "content":"\nThis post copied from my World Without Apps site.\n\nIn my first post, I defined what I mean when I talk about the World Without Apps (WWA), the premise for this site. I may not have been entirely honest with you.\nIn reality, I recognize that we're really never going to enter a world without any apps, what we're really entering is a world with less apps (WWLA). The reason I picked WWA instead of WWLA is that WWA is, well, more aggressive. Is it more startling to think of a world with no apps then work backwards to a realization that we'll really have less apps going forward or to start with WWLA and leave it at that?\nI think we need to focus on WWA - work to understand what that means then focus our development efforts on delivering that world to the betterment of, well, everyone. Will we ever get there? Perhaps, but likely not soon (in the next 10 years). But, if we can simplify app-like capabilities and interaction interfaces to the point where more can get done without needing fingers poking at glass (FPAG), then we've accomplished something.\nWill we continue to need apps? Yep, absolutely. There are many data input, data browsing and analysis apps that could be delivered without apps and screens, but those will primarily be enterprise apps and the subset of data-driven apps that consumers need (such as banking, travel and so on). In those environments, I expect that voice will continue to be the primary interaction, and smartphone or tablet screens simply being data display or data-interaction targets.\nAs agents become more capable, they'll take over more and more tasks from apps leaving few apps around for us to use.\n",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
  ]
  },

  {
  "title": "What is the World Without Apps (WWA)?",
  "date":"Sun Jul 31 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1470009600,
  "url":"/posts/2016/what-is-the-world-without-apps-(wwa)/",
  "content":"\nThis post copied from my World Without Apps site.\n\nAs I launch this site, it seems appropriate to describe the overall premise its built on.\nMobile as a product category is changing lives everywhere. Everyone reading this article probably has a smartphone and likely has at least one tablet as well. It’s even likely that this article’s being read on a mobile device as well since desktop PCs and even laptops are less frequently used for web browsing. What makes mobile devices so useful and popular are the apps the devices execute to enable its user (you) to accomplish things. From the beginning of computer time, apps have been hand crafted by one or more software developers to accomplish something. App users use one or more apps to deliver some result. If one app is enough for a job, users fiddle with fields, buttons and menus to, well, do something. If one app isn’t enough, users learned that they could take the outcome (results) from one app and plunk it into another app to get the next result, stitching apps together in series to reach a specific goal.\nWhat then is The World Without Apps? Well, it’s being able to accomplish a specific goal without using any apps at all. We’re in a world driven by apps today, but we’re quickly moving to a place where apps are no longer necessary for many tasks. Let me see if I can explain…\nEarly Inter-app Interaction\nWhen Microsoft created Dynamic Data Exchange (DDE) and later Object Linking and Embedding (OLE), amazing new things were possible. An app could now call out to another app and execute some task, then use the results. This enables developers to dynamically link apps, building apps that focused on a limited set of tasks, then stitch together those apps to deliver a more…sophisticated result. This was a great capability, although a bit flaky. This inter-app communication capability created dependencies and the potential for memory leaks that could wreak havoc in complicated processes and on computers with limited resources.\nInter-app Interaction on Mobile Devices\nIn mobile apps, this interconnection is easier – it’s a simple process to enable capabilities in an app that can be invoked from another app. Apps can publish capabilities that only sibling apps can invoke (a secure approach) or an app can publish capabilities that any app can invoke. With this last approach, an app tells the OS it wants to do something (usually through a file or URI) and any arbitrary handler can respond indicating that it can handle the task. This works, but unless each program involved in the activity was coded by the same developer, the app initiating the request can’t necessarily control what happens in the invoked app.\nAgents to the Rescue\nVoice added an interesting interaction to mobile devices. Now, instead of poking around at different apps, you could simply tell the device what you wanted and it would try to figure it out for you. Basically this is nothing but voice enabled search – the ability to speak a query instead of type it in. The voice interaction system had the ability to perform certain tasks for you such as opening an app, calling a specific contact or specified phone number or even sending or responding to text messages. Beyond delivering search results for you, the extra capabilities provided by voice enabled search exist only because the browser or the mobile device OS developer added additional capabilities – code-locked capabilities that can only deliver what a developer has coded the engine to deliver.\nWith Google Now, Google added capabilities to the Android OS that enables the device to guess some information that you might find helpful and deliver that to you through a special panel and, later, through notifications. Apple even added a vaguely similar capability to iOS where an extra panel was added to the home screen where iOS tries to guess what apps or information you’ll want to use next. Microsoft’s Cortana can do a little of that as well, but you have to invoke her to gain access to that feature. This means is that your mobile device is figuring out how it can help make your next task easier for you. This approach is the first step in the World Without Apps.\nIt’s pretty interesting how quickly this became a very capable service. I remember going to a concert with my son and noticing that my Android device starting letting me know that it knew how to get me back to my car and also how long it would take me to drive home. When out for lunch, Google Now would start notifying me how much time I had before I’d need to start heading home in time to make my next call or how long before I’d have to leave to make my next appointment.\nThe most startling example was when I was driving from Raleigh to Charlotte and Google Now notified me about an accident on the highway in front of me. What was most surprising about this is that I wasn’t using the device’s navigation capabilities (Google Maps), I was instead using the navigation system built into my car (which my p",
  "tags":[
  
    "post"
  
  ],
  "categories":[
  
  ]
  },

  {
  "title": "Doing Account Creation Right",
  "date":"Wed Jul 27 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1469664000,
  "url":"/posts/2016/doing-account-creation-right/",
  "content":"As I strive to pick up new technologies and start new projects, I'm regularly finding myself registering for new services, accounts or access to specific websites or forums. As part of this process, I've noticed two things:\n\nVery few web form developers use the (no longer) new HTML input types (https://w3schools.com/html/html_form_input_types.asp) like email, date, time, url, and so on.\nSecurity requirements force a specific set of minimum password requirements, but web form developers rarely let you know that they even exist, or what they are, until AFTER you've submitted credentials that don't meet the requirements.\n\nIn my mind, the first one indicates that the developer isn't thinking about mobile users (which have special keyboards for the specific input types) and isn't interested in making input easier on mobile devices. I wrote a post about this topic and shared some examples, so this isn't the focus of this post.\nThe second one tells me that developers aren't thinking very carefully through the whole registration process. They seem to feel that the present, populate, submit, validate, kickback, fix, and submit again process is reasonable for registrants, when a simple present, inform, populate, submit, and validate process is much more efficient (see Figure 1).\n\nFigure 1 – Registration Process Flows\nUnless I'm able to somehow divine the password requirements in advance, without you telling me, the registration process most developers implement forces users to submit the registration form twice. I don't have the numbers, but it would be very interesting to see some analytics data on one of these forms to see how often users are actually able to guess the password requirements. For sites with more complex password requirements, I imagine that the number of users who have resubmit is at least 80%.\nWhat developers must do is list any password complexity requirements on the registration form from the very beginning. When you do this, you'll eliminate the majority of your validation errors except for those cases where the user isn't paying attention. I'm experienced, so I know that most sites will have password complexity requirements, so I'll look for details regarding the requirements before I tap the submit button. If I don't find them, which is the majority of the time, I pick a simple password and submit it to see if it will work.\nWhat most developers do, is assume it's OK to tell the users what the password complexity requirements are during the validation kickback process. That works, but it's too late. The user has already made an investment to populate the form using all of the information you provided and you failed him. This approach requires that the user fail before they're provided with the information they need to be successful. If they're successful on the first try, it's because:\n\nThey made a lucky guess\nThey're default approach to passwords accidentally meets your minimum requirements\nYour password complexity requirements are not complex enough for most users\n\nThe folks at MongoDB recently launched a cloud hosting service (cloud.mongodb.com), and did a really great job on their registration form (see Figure 2). Not only are you told up front what the password complexity requirements are, you can see visually how many of the requirements you have met. That's the way it should be done. At a minimum, list the requirements on the form from the moment it's served. As a bonus, show the user how they're doing as they populate the form.\n\nFigure 2 – MongoDB Cloud Registration Form\nUnfortunately, the MongoDB folks failed at using the right input types in their form. The email field doesn't use the email input type, so on a mobile device users won't see the email input keyboard. Too bad.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Formatting Email Content for Usefulness on Mobile",
  "date":"Tue Jul 26 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1469577600,
  "url":"/posts/2016/formatting-email-content-for-usefulness-on-mobile/",
  "content":"I posted a little while ago about how marketing organizations were ignoring mobile clients when crafting email blasts and provided some examples (which I continue to update as I find more). My analysis of these emails focused mainly on how the email messages are not formatted correctly for smaller devices, but as I looked into this more, I realized that many of these email messages, not marketing blasts, but specific notification emails sent directly to me, weren't structured in a way that made them immediately useful to me as the consumer. Take the following email notification from American Airlines for example:\n\nFigure 1 – American Airlines Departure Reminder Email\nWhen you look at the email on my Nexus 5x device as shown in the figure, there is no useful information displayed once I open the email. All I can tell by looking at this email is that I have a departure coming up and that it has a specific record locator. The developer who crafted this email message paid no attention to providing me with useful information above the fold (in the first page displayed).\nWhen companies craft notification messages, they need to focus on organizing the content so the reader gets the most important information as quickly as possible. Newspapers and even magazine articles are structured in a pyramid format, with the most important information at the top of an article. They do this so that editors can easily trim the article to fit a particular amount of available space without losing the story; the side effect is that users get more quickly to the important part of the content.\nFor mobile app content, content creators must focus on getting the user the pertinent details of the notification without forcing the user to scroll the page. As you can see from the figure, there's information there, but it's all (yes, all of it) useless. Users have no choice but to scroll the message in order to see the details.\nLet's analyze the email content…\nIn the subject line, for example, I can see that it's a departure reminder. That's good, I guess, but I probably already know that I'm departing today. That text clarifies whether the email is a departure reminder or some other type of notification, so I guess that's OK, but still not a very good use of the space. Next they tell me it's a reminder for, well, me. This email was sent to my personal inbox, who else would the reminder be for? Why do they have to inform me that the reminder is for John Wargo when they know they sent the reminder to John Wargo's email account?\nNow, I recognize that some executives have their travel managed by their assistants, and those assistants may cover multiple executives, so letting me know who the reminder is for, in that case, might be useful. But, of the millions of users who receive these notifications, how many of them are sent to assistants? 1%? 5%? 10%? Should you accommodate the outliers or do you accommodate the majority of your users when formatting notification content? The majority, please; there's no need to remind me that the departure reminder I'm getting is for me. If you're sending me a departure notification for someone other than me, then including the name of the traveler does make sense. So, for example, if sending a notification to my wife, which is something I have setup in my AA account, it would make sense to include my name in the reminder email. But, any departure notification she's going to receive is either going to be for her or for me, so there's still no need to include the traveler's name in the subject line.\nNext, the airline included the record locator for the flight I'm being notified about. That's nice, but what am I supposed to do with that information? The record locator is useless information to me at this stage of my traveling experience. I know I can use the record locator to locate my record, and view the details of my current trip, but the app creating this email already had the record open, so why not skip the record locator and actually include details from the record instead?\nWhen you get to the body of the email, American Airlines has decided to include a header graphic that has their logo, plus links to perform actions on their web site. I understand the value of the brand's header graphic at the top of the email, that's expected. But why do they think I need a link that allows me to book a flight at this time? They're reminding me about a flight departure, and, so far no details about the flight's actual departure has been provided. However, I've been given a link to use to do more business with the airline. Does that make sense? Also, as you can see, they didn't format the header so it scales correctly on the page, so other potential useful information is off on the hidden right side of the screen.\nNow onto the body of the email. As you can see, the content styling isn't setup to automatically wrap the content to the page width. You're teased that there's details about this particular flight coming up",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PyMongo & Google Charts Data Tables",
  "date":"Wed Jul 20 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1469059200,
  "url":"/posts/2016/pymongo-google-charts-data-tables/",
  "content":"I'm working on a project that involves graphing data from a MongoDB collection using Google Charts. For this particular project, I'm collecting weather data (temperature, humidity, and barometric pressure) data on a Raspberry Pi, storing it in a MongoDB collection and delivering a web interface for viewing and graphing the data. I'm built the web interface using Flask (https://flask.pocoo.org/), so there's some flaskness in the sample code.\nAs I worked on the part of the web app that graphs the weather data, I decided to use Google Charts as the client-side rendering library. I'd not worked with it before, so this seemed like a good way to learn it. As I poked and prodded at the Charts documentation, I learned that I had to deliver my data in a specific format for Google Charts to be able to make use of it, and the data coming out of the Python Mongo driver (pymongo) wasn't giving me what I needed, or at least, wasn't giving it to me in a usable format. I had find working, so I was able to get the data I needed from the collection, but it had to be reformatted before sending it to Google Charts.\nHere's a complete Python snippet that shows how to do it:\n\nLet's tear apart the code…\nTo query the Mongo collection, you use pymongo's find() method:\n\nIn this case, I pass in a Python object describing the search criteria, {} to get all documents for example, which fields I want returned and a specific sort order. I'm not going to describe each of those as the Pymongo documentation describes them pretty well.\nThe call to find() returns a cursor, basically a pointer to a result set. To process the results, you can iterate through the cursor, which I'll show you in a minute, or you can simply return the data in the default JSON format using:\n\nIn my use case, I needed the data as an array of arrays (the Google Charts Data Table format), so I'll have to iterate through the results and build my array of arrays as I go:\n\nThe first thing the code does is checks to see if there's even a cursor; just in case the call to find() failed for some reason. Once the app knows it has data, it loops through the data and creates an array containing the measurement values then appends the new array to an existing array of results data.\nWhere the call to dumps(cursor) would return something like the following:\n\nThis code returns something like the following:\n\nAlthough I am taking a little liberty with the time format, the examples are just examples of format, not real data.\nNow, if you know anything about Google Charts Data Table format, you were probably wondering why I didn't include any column information in the results returned from the server app. That's because this app accommodates mobile devices and, since the column data never changes, I chose not to send it repeatedly over the wireless app. Instead, I added the code to setup the data table on the client application in the following JavaScript code:\n\nI'm still working on the project, so the code's not complete, but you will be able to find the complete project source code at pi weather monitor once I complete the project.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Pi Reminder – Delete Google Calendar Access Authorization Token",
  "date":"Sat Jul 16 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1468713600,
  "url":"/posts/2016/pi-reminder-delete-google-calendar-access-authorization-token/",
  "content":"Note: This article refers to an older version of the Pi Remind application. In a subsequent update to the Google libraries, Google now places its configuration file in the same folder where the application executes. Refer to the project's readme for additional information.\nI'm in the process of changing jobs, so after I left my previous employer's employment, I needed to reconfigure the Pi Reminder app to point it to my personal calendar profile instead of my work profile. If you remember the process, when you execute the Pi Reminder code on the Raspberry for the first time, it walks you through a process of authorizing the app to access your calendar (shown in Figure 1).\n\nFigure 1 – Authorizing Pi Reminder to Access a Google Calendar\nWhen you complete this process, the Google Calendar API creates a hidden file on the Pi that contains the access token generated as part of this process. When it's time to switch the Pi Reminder to use a new profile, all you have to do is delete that file.\nNote: Before you can continue, you'll need to stop the pi_reminder.py process as it's using the file we need to remove. If you ran the application manually in a terminal window, just terminate the process by closing the terminal window. If you're like me and you used the desktop file I included in the project, then you'll need to delete the file in the ~/.config/autostart folder. You can delete it then reboot the Pi before continuing with the remaining steps. Once we're done, restore the file from the trash, reboot and you'll be all set.\nIn my experience, Python code doesn't like running as the Pi user, so in my instructions for starting the Pi Reminder code, I had you execute the code using the Linux sudo command. A side-effect of that is that the Google Calendar access token file is created by the root user and is not visible to normal users like the pi user. So, to whack the file ('whack' is a technical term for 'delete') you'll need to do it with elevated privileges.\nNote: There's probably a lot of different ways you can do this, but I'm not a Linux expert, so I'm just going to show you how I did it. If you have a better way, that's great, I don't necessarily need to hear about it since this approach worked quite well for me.\nStart by opening a terminal window. Once there, execute the following command:\n\nThe terminal will display the output shown in Figure 2 then open the Raspbian file manager application (shown in Figure 3), PCManFM.\n\nFigure 2 – Raspbian Terminal Application\nIn the file manager, navigate to the file system's /root folder as shown in the figure then double-click the .credentials folder to open it.\n\nFigure 3 – Raspbian File Manager\nInside the folder is a file called pi_remind.json (shown in Figure 4), that's the file we're looking for. Delete the file then close the file manager.\n\nFigure 4 – Google API Access Token File\nNext you'll need to authorize Pi Reminder to use a different account with Google Calendar. Follow the instructions included with the original article to complete that step.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Defective Astro Pi Sense HAT Boards",
  "date":"Tue Jul 05 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1467763200,
  "url":"/posts/2016/defective-astro-pi-sense-hat-boards/",
  "content":"I'm working on a project that uses the Astro Pi Sense HAT board to measure temperature, pressure and humidity. The project I'm building will upload weather measurements to Weather Underground, but I'm also storing the data locally (in a Mongo database) and building a dashboard my family can access to view the captured data using Flask.\nAnyway, I've been having problems with the Sense HAT board, I've purchased two of them and they both recorded invalid data. The vendor finally admitted that 'We reached out to the manufacturer. There are issues with the current ones on the market and it will not be resolved until late July.' So, apparently the batch of devices out in the wild won't work and I'll have to wait until probably early August for a working board. Since I searched the Internet and couldn't find anything about this problem, I thought I'd post it here so others can save themselves some troubleshooting.\nHere's the results I got from my second Sense HAT board:\n\nThat temperature reading? It's in degrees Celsius - can you imagine 140 degrees C?\nAnyway, here's a quick test application you can use to, well, test the board; this is the app that generates the output you see in the figure:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Relay Testing Jig",
  "date":"Mon Jun 20 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1466467200,
  "url":"/posts/2016/relay-testing-jig/",
  "content":"I've been doing a few projects lately that work with relays. One was a Particle Photon project that I hope to write about soon, and the other is a Raspberry Pi project that I've not completed yet. As I worked on each of these projects, I found myself wiring up one or more LEDs and connecting it to the microcontroller so I could validate whether the code is working correctly. Yes, I know I could tell the relay is firing by the click it makes when I fire it, but I wanted something visual.\nAnyway, while browsing around on the Adafruit web site, I discovered their Perma-Proto boards (https://adafruit.com/products/591). These things are breadboards (of a sort) that you solder components into. They're a nice, easy way to quickly build projects in a more permanent way.\n\nImage 1: Adafruit Proto-board - Image used with permission\nI bought a handful and they sat around for a while looking for something to do. As I wired up yet another LED configuration, I remembered these boards and started thinking. I decided to create a relay testing jig using a proto-board, some LEDs, resistors and a battery. You can see the finished project in the following figure.\n\nImage 2: Relay Testing Jig\nThe battery provides power for each of the LEDs, but the negative wire to the LED is broken (the pairs of colored wire at the top of the figure). When you put AA batteries in the holder then collect one or more pair of colored wires to a relay, you have a simple jig you can easily wire in to help you test the software before you finish building the final hardware project. Connect both wires of the same color to the relay's NO or NC connections and you're set.\nHere's a rough circuit diagram. My long term goal (who knows, perhaps it will become a short term goal) is to learn how to use Fritzing. Once I do, I'll come back and provide a circuit diagram for this project so you can easily create your own.\n\nImage 3: Circuit Diagram\nNow, whenever I'm working on a project, I can grab this jig and be up in running in seconds.\nMy plan is to make another one that I'll use for testing GPIO ports on a microcontroller. This version will not be battery powered, but will instead get its power from the controller whenever the connected GPIO port goes high.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Pi Reminder Updates",
  "date":"Mon Jun 20 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1466467200,
  "url":"/posts/2016/pi-reminder-updates/",
  "content":"My Pi Reminder project went online at Makezine.com and since then I've been hearing from readers. One reader has made a couple of updates to the code which are now available online at https://github.com/johnwargo/pi-remind Here's a summary of the updates:\nTime Zone Processing\nThis project is my first attempt at Python coding; I was surprised at how quickly I was able to pick it up. That 30 years of experience in software development really paid off as I was working to learn Python. As I coded the app, I had to work though how to manipulate the Google Calendar's use of UTC. To filter the event list to return only appointments in the future, I had to convert the current time to UTC and pass it to the cloud API. I poked around a bit and struggled a bit to figure out how to get the time in the right format, so I hardcoded my current time zone in the conversion process. I expected that I'd point this out so other folks could adjust that calculation for their time zone, but forgot to do so in the original article. Fortunately for me, reader John McCabe ran across this hardcoded code and implemented a nice, clean fix for it which I've merged with the live code.\nEmpty Event Descriptions\nWhen I built the app, the only calendar I had to work with was mine. As I use the calendar in a work environment, all of my events were in pretty pristine condition. Unfortunately, the code didn't take into account events that didn't have a summary (a description/title). I'm not sure why you'd want an event without a description, but I tested it and apparently Google Calendar doesn't mind. John McCabe implemented a fix for this and I've merged it in. He also taught me an interesting way to use Python's if-in capability in the process.\nKnown Issue: Cancelled Events\nI recently noticed that Pi Remind was notifying me of canceled events. I have the Google Calendar feature enabled that allows me to see canceled appointments on my calendar. I enabled this in case I declined an invitation but later found I was available to attend. The Google Calendar API returns those canceled events, even when I have showDeleted set to false, so this is an open issue I'm going to have to fix. Stay tuned on this one.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Raspberry Pi Reminder App",
  "date":"Wed Jun 15 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1466035200,
  "url":"/posts/2016/raspberry-pi-reminder-app/",
  "content":"I work at home and I spend a lot of time on the phone talking to clients and vendors. My employer uses Google Apps (which includes Google Calendar and Gmail) and the appointment notification capabilities of both are not very robust. Well, they're robust, but not enough to get me to actually show up for calls on time. What I find is that I often miss the notification when I'm busy doing something else or I notice the notification, but quickly forget about just a few minutes later and ultimately miss some meetings or join late.\nOne day, after being 15 minutes for a meeting, I decided I had to fix this problem. I needed a more effective way to alert myself of upcoming appointments. As I spend a lot of time on the phone, I didn't want an audible alert, so I decided I'd do something visual. While browsing the Adafruit web site, I noticed the Pimoroni Unicorn HAT and that had me thinking of solution. The Unicorn HAT is an add-on board for the Raspberry Pi that consists of an 8x8 array (that's 64 total if you're counting) of bright RGB LEDs. What if I wrote a Raspberry Pi application that connected to Google Calendar and checked my calendar for my next appointment then flashed those 64 LEDs to let me know? As long as I was conscious, and in the room, I'd likely see them and decrease my chances of missing an appointment.\nMake Magazine just published an article I wrote about this project at https://makezine.com/projects/get-a-flashing-meeting-reminder-with-a-raspberry-pi You can see the final project in action at https://youtu.be/X111pAaEP-k\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "AT&T's Network Couldn't Handle the 2016 Indy Crowd",
  "date":"Mon May 30 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1464652800,
  "url":"/posts/2016/at&t’s-network-couldn’t-handle-the-2016-indy-crowd/",
  "content":"I attended the 2016 Indianapolis 500 race last weekend. On Sunday morning, we (me and about 500,000 people) headed to the speedway for the largest single day sporting event EVER. We parked very close to the track ($100 and worth every penny) and did some tailgating. A short time after I got there, I looked at my phone to find the following error:\n\nHere's a screen shot of the error:\n\nFigure 1\nWhile the error message isn't very clear, I wasn't surprised. Even though Verizon sponsored the event, I'm sure of the 500k participants at the race, a good many of them were AT&amp;T customers and the network simply got overloaded. Having previously worked at AT&amp;T, I know they work really hard to accommodate large crowds at events, but this one, being the largest event EVER, was probably more than they could handle.\nA former colleague apparently tried to call and text me during the race in order to meet and grab a beer, but he was never able to get through to me. After leaving the event everything went back to normal.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Poorly Designed Notification",
  "date":"Sun May 01 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1462147200,
  "url":"/posts/2016/poorly-designed-notification/",
  "content":"I really enjoy analyzing apps, notification emails and other technological implementations looking for ways that developers have failed their audience. I like this not because I like to pick on others, but because it helps me learn what not to do in my own app implementations.\nI was traveling last week to the Xamarin Evolve conference and received the following text message from my primary airline:\n\nI already knew about the gate change, so I didn't pay much attention to the notification until later when it struck me that American Airlines really failed in getting me the information I needed.\nDon't get me wrong, I like getting the notifications, but this one isn't useful to me until I open it. It's telling me there's a gate change, great, useful information. What's the next piece of information I need? Well, I do need to know which flight, but in this case, I only had one flight that day, so telling me what the flight number and the source and destination airport is useless to me. If you think about it, unless you're someone who memorizes flight information, then the only really important information for me is the departure and arrival cities.\nAnyway, what's the next most important information? The new gate number. In this example, they're telling me there's a gate change, good information to have. Next they're telling me which flight – good, that's good. The next most important information for me is which gate do I now have to walk to? Remove the flight number and the word 'departing' and there's enough information there to tell me everything I need to know to get to my new gate:\nGate Change: CLT-MCO now Gate 54\nAnything else, absolutely anything else, is bonus information. If there's room for it on the messages list, then I'd see it, otherwise I only have to open the message to see the less important information. The way American Airlines has implemented this, no matter what happens, I must open the message to view the most important aspect of the message.\nSee what I mean? The developer implementing this should have prioritized all of the data and ordered it with primary data first. That would save me the extra click required to open the message.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "iOS Forcing Me to Delete Mail Messages Twice",
  "date":"Sat Apr 16 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1460851200,
  "url":"/posts/2016/ios-forcing-me-to-delete-mail-messages-twice/",
  "content":"Once again iOS is making my life harder for me. I'm one of those people who has a desktop PC and use it for writing, coding, gaming and more. I have several mobile devices (a couple of tablets and a smartphone) and I have my email accounts configured on each. What I want is that if I've read and deleted an email from any of my devices, the email message is no longer available on any of those devices, including the desktop.\nUnfortunately, that won't work. Apple, in its infinite wisdom, has decided that when I delete a message from my inbox on iOS that I really don't want it deleted from my device right now. As you can see in Figure 1, when I delete a message from my inbox, the soonest it will be deleted from the server is after one day.\n\nFigure 1\nAlso, with Apple's email services, what seems to be happening is that Apple is downloading new messages for me in the background (at the server level) and delivering them to the device when I open the email client. So, what this means is that if I've opened my mail on my desktop and filed and/or deleted all messages, when I open my iOS mailbox, I'm going to have to go through all of the messages and delete them again.\nI can't win; either I have to delete the messages on my iOS device after already processing them on my desktop or I have to deal with them all over again on my desktop after reading and deleting them on my iOS device.\nWhy does Apple work so hard to make things difficult for me?\nI can understand why some people will want to be able to keep deleted messages for a while, but why completely remove my ability to delete it everywhere when I delete it from my iOS device? Why not set a reasonable default option but still give people like me the options that matter the most to me? Ugh.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Android HTTP POST Request Using OKHTTP",
  "date":"Sat Apr 16 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1460851200,
  "url":"/posts/2016/android-http-post-request-using-okhttp/",
  "content":"I'm not much of a Java developer. I've poked and prodded at it when I worked for BlackBerry and wrote my BlackBerry development book, but I've not done much serious Java development in my career. I've been working on a Particle Photon-based garage door controller and I built a web app and an Apache Cordova version of the app to interact with the controller. I also wanted a native Android app for this, so I got to work learning Android development. I picked up a copy of the Big Nerd Ranch guide to Android Development (https://amzn.to/22D68vF) and got to work.\nAs I learned new skills working through the guide, I'd finish a chapter then go back to my garage door controller app and implement it there as well. I reached a point where I had everything setup on the photon and the Particle cloud with the app well tested using the web and Cordova versions of the controller app. At this point, I needed to be able to do an HTTP POST from the Android app. I got an example of it working with the standard Android HTTP libraries, but I was looking for a simpler implementation. I stumbled upon the OKHTTP library and tried to figure out how to make it work for me.\nI needed to send an HTTP POST to the Particle Cloud and I couldn't find a single example that showed me how to do it using OKHTTP. There were a lot of REST examples, with parameters passed on the URL, but for this project I needed to populate the request body with some parameters. I couldn't find a complete example, so I had to post this one here.\nInitialize OKHTTP using:\n\nTo create the POST body, use:\n\nEach request parameter is added to the body using .add().\nTo call the REST service, use:\n\nThe code is executed in a runnable (so that it will run on a background thread) and success and failure processing are done within the runnable:\n\nYou can find the full code posted as a Gist on GitHub at https://gist.github.com/johnwargo/9a4bf307287b5d808b089e5e2932c091. The code is for a menu item in the app that allows the app user to create a single use code that allows others to open the garage door (once). It generates the code then sends it to the Particle device through the Particle Cloud. Override mode is set based on the phone number for the device. If it's my phone or my wife, this menu item will appear in the app. For my kids, the menu's empty (we don't want them sending a single use code to anyone).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Nexus Support Euphoria",
  "date":"Fri Apr 15 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1460764800,
  "url":"/posts/2016/nexus-support-euphoria/",
  "content":"I switched to Android a few years ago. I was a diehard BlackBerry fan for a very long time, but things just got ... weird with BlackBerry, so I migrated to Android. I've had several Samsung devices, but I didn't like any of them because Samsung adds too much extra junk to Android. Give me pure and simple Android and I'm OK.\nLast Christmas, I invested in a Google Nexus 5x device. Having owned several Nexus 7 devices, I knew this would be a good device for me. I especially liked the device because of fingerprint scanner on the back. My employer rightly requires a password on the device and I was essentially not able to use any of the voice commands while driving simply because it was too hard to unlock the device while driving. The fingerprint scanner on the 5x is awesome since all I have to do it tap it with my (registered) finger and the device unlocks.\nAnyway, last weekend I was making an update to the garage door controller app I wrote and plugged the device into my development system to install the latest version. Immediately Windows started complaining about a power surge in the USB port and shutdown the port. I scratched my head a bit, poked around and discovered that the device wasn't charging using any chargers or USB cables. Since changing cables didn't change anything, I knew the device was hosed.\nThe device is only about 3 months old, so I knew I'd be able to get warranty repair for it. The only thing I didn't know was how to get that support and how painful it would be. Little did I know that I was way, way off on how hard it would be.\nI waited until Monday to work on this and started my day by searching Google for nexus 5 repair. I quickly found the official support page and with the minimum of clicks I was on the phone with an English speaking support technician. From the site I was able to request a callback and within seconds someone was helping me. No IVR hell, no waiting in a queue, no having to prove that I'd done all the right things to troubleshoot it. The technician listened to what I told her about my troubleshooting steps, agreed with me that it was broken and worked very hard to get it fixed for me. I was amazed.\nIt took me about an hour on the phone to get this all resolved – not because it was hard to work with her or she had multiple steps to go through to get my device fixed. Instead, neither of us could find my order, so that is the only reason it took so long. Whew.\nI received a replacement device the very next day.\nI don't know if you've migrated between Android devices lately, but the process is pretty cool. During setup of the new device, you're prompted to go to your old device and start the migration process. Once started about two minutes later everything (and I pretty much do mean everything) is transferred. I had to redo my Bluetooth pairings and login to my apps, but everything else was completely taken care of for me. Excellent.\nBeing a modern, technical guy, I immediately tweeted about my euphoria over my support experience:\n\nWithin seconds, someone from the Google Nexus support team saw my tweet (OK, it's probably a bot, but who cares – this is cool) and offered to help:\n\nSo, I didn't even have to go to the support site, I could have tweeted “my Nexus 5x is broken” and gotten immediate help. How cool is that?\nThe conversation continued:\n\nAnd the helpful, happy response:\n\nAnyway, I'm pretty impressed with how easy this was. The device broke, which I'm not entirely happy about, but the experience was so painless that I simply didn't mind. Well done Google (LG).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Arduino Powered Pinewood Derby Car",
  "date":"Wed Apr 13 2016 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1460592000,
  "url":"/posts/2016/arduino-powered-pinewood-derby-car/",
  "content":"This content was originally published online in Make Magazine at https://makezine.com/projects/arduino-powered-pinewood-derby-race-car/. A PDF version of this article can be downloaded from a link at the bottom of the article.\nIntroduction\nBy John M. Wargo &amp; August M. Wargo\nAugust: My dad and I had an idea that our last pinewood derby car should be really cool. My dad is a geek and really good with electronics so he did most of the coding. I did most of the design. I thought that it was a lot of fun because I got to spend more time with my dad and got to do a lot of things that I like. I couldn't wait until the race to see how fast it was. It did not win a single race. But we did win the most unique car design. It was the best Cub Scout experience I've ever had.\nJohn: My son is in Cub Scouts and for years we've been building Boy Scouts of America Pinewood Derby (pinewoodderby.org) cars with the rest of the pack. I've always invited my son's Den into my workshop so the other scouts and their Dads can make use of my tools to build their cars. The Boy Scouts has a policy against Cub Scouts using power tools, but with the right guidance we've gotten along.\nIt's always…interesting to see how much involvement the Scouts have vs. their parents in making the cars. For the most part, I've let my son do what he wants with his car; I've guided him, but let him cut the car, sand it, paint it and so on. I really only got directly involved when it came to putting the wheels on as he didn't, until recently, have the physical strength and control needed to do that right.\n\nFigure 1 – A Boy and His Arduino Powered Pinewood Derby Car\nAfter watching one particular parent last year spend two hours or more in the shop painstakingly cutting, shaping, sanding and grinding the car into a particular shape, my son and I decided that we'd kick it up a notch this year. Even though I have a pretty nice wood shop, I'm more of a programmer type (I've written 6 books on mobile development), so I suggested that we do something with a programmable microcontroller and some LEDs for this year's race. I'd wanted to do something with Arduino, so this seemed like the perfect opportunity to do so while at the same time providing me with a chance to teach my son how to wire things together, solder and write code.\nIn this project, we'll show you how to create an Arduino-powered Pinewood Derby car. We'll be using an Arduino (arduino.cc) microcontroller board, some LEDs and an accelerometer to flash a set of LEDs depending on the orientation of the car.\nFor our first iteration of this, we configured the car so that when it sits in the pits, it will flash the lights in a certain pattern. When the car is at the starting gate, and when it's on the angled portion of the track, the light pattern changes and becomes much more active. Knowing that the car may jump off the track, we also added special added patterns for when the car is sitting on its left or right side. Since everything is done in code, it's super easy to completely change the light patterns and orientation settings in the software. You and your son can spend hours trying out different patterns to get the right, and potentially unique, ones for your car.\nSource Code\nThe project's Arduino source code available at https://github.com/johnwargo/Arduino-Pinewood-Derby.\nMaterials\nThe project uses the following materials:\n\nOfficial Pinewood Derby car kit (2 or more: if you're like me, you'll make mistakes and need to start over). Available at any hobby or craft store or at https://pinewoodderby.org/#/three.\nArduino compatible microcontroller (1: for this project, I used a Teensy 3.0 https://pjrc.com/store/teensy3.html)\nArduino compatible battery (adafruit.com/products/258)\nBattery charging module (adafruit.com/products/259)\nPower switch (adafruit.com/products/1400)\nAccelerometer (adafruit.com/products/163)\nLEDs (3.7 V or higher) with matching resistors (10)\nRibbon cable (2 feet: https://sparkfun.com/products/10647)\n#2 wood screws (minimum 12: https://grainger.com, part #1LB35)\n#2 nylon washers (minimum 12: https://mouser.com, part #534-3347)\nRed and Black connector wire (24ga or equivalent)\nPrototype board (https://veroboard.com)\n\nTools:\n\nPencil\n12 inch ruler\nX-acto knife or similar\n½ inch or smaller Chisel\nSoldering Iron &amp; Solder\nEpoxy\nPaint, brushes, sandpaper\nHand saw, band saw and/or table saw\n[optional] bench sander\n\nHere are some details on the project’s components.\nArduino Board\nThe Arduino is an open-source programmable microcontroller. As its open-source, there are a lot of different versions of the board available. The Arduino team has designed some boards and different parts of the community have implemented their own designs. If you look on Maker Shed (https://makershed.com/collections/arduino-boards) you'll find a bevy of devices available of all sizes and capabilities.\nYou can use whatever Arduino compatible board you want, but since the Pinewood Derby car has specific requirem",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)",
  
    "Arduino"
  
  ]
  },

  {
  "title": "Particle Garage Door Opener Code Published",
  "date":"Thu Mar 10 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1457654400,
  "url":"/posts/2016/particle-garage-door-opener-code-published/",
  "content":"I've been working on a project using the Particle Photon wireless device. It's a garage door controller that uses a Photon plus a smartphone app. I'm planning on writing an article about the project soon, I have to get this all installed and working first, but in the mean time, all the code is done, so I posted it to my GitHub account yesterday. Stay tuned for the full article on how I built this thing and how it works. Here's the final product.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "My Books In the Singapore Library",
  "date":"Thu Mar 10 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1457654400,
  "url":"/posts/2016/my-books-in-the-singapore-library/",
  "content":"\nI'm not sure what this means, but a former colleague shared this image with me. Apparently the Singapore Government Library web site has entries for some of my books. How cool is that?\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Particle Photon Function Not Found",
  "date":"Wed Feb 17 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1455753600,
  "url":"/posts/2016/particle-photon-function-not-found/",
  "content":"Lately, I've been working on a project using the Particle Photon. The project's been 'done' for some time now; the code's all written and the hardware is all soldered together. I'm ready to install it, but, of course, I've found some additional functionality I want to add to the associated Android app. So, I added a couple of additional functions to the Photon's code and started testing them using the Chrome Advanced Rest Client.\nDuring my testing, I encountered the following error:\n\nOf course, I studied my Particle C code for a while looking for the problem to no avail. I could not find the problem.\nI have three functions in my app, so I thought for some reason the Photon was limited in how many functions you could have (turns out the limit is 410). To test this theory, I reordered the functions to see if the one I was having trouble with would work if it was higher in the list. Nope, that wasn't it.\nI noticed that the function that wasn't working had a name longer than the rest, so I shortened it and suddenly it started working. If you encounter this issue, know that the maximum function name length is 12 characters. What I don't understand is why this is even an error I had to figure out. The Particle Cloud is parsing the request and looking for a function that matches the name I've provided on the URL. If the functiion name is longer than 12 characters, then tell me that I've passed a function name that's too long. Don't tell me you can't find the function. I knew I was providing the right function name, the one that matched my code, but the Particle Cloud couldn't recognize it because it's too long - that's the perfect time for an error message back from the service that reads something like &quot;The function name is too long.&quot; That, for sure, would have shortened my troubleshooting time.\nYou can find the complete documentation here: https://docs.particle.io/reference/firmware/photon.\nPostscript:\nOK, so I learned a few things since posting this. I submitted part of this article to the community forums and got a bunch of responses. Several people who responded seemed to think that it was a good idea to fix this. Unfortunately, many other folks had a pretty antagonistic attitude about this; apparently they think this is pretty clearly documented and there's no reason to make this idiot (me) proof. So, if you're just getting started, recognize that the Particle Community doesn't care to catch some errors you may have missed.\nThe documentation at the link I provided above says the following:\nCurrently, up to 10 cloud variables may be defined and each variable name is limited to a maximum of 12 characters.\nSo, for cloud variables, there can be no more than 10. My bad, I thought that applied to functions; for functions, the limit is 4:\nCurrently the application supports the creation of up to 4 different cloud functions.\nIn order to register a cloud function, the user provides the funcKey, which is the string name used to make a POST request and a funcName, which is the actual name of the function that gets called in your app. The cloud function can return any integer; -1 is commonly used for a failed function call.\nThe length of the funcKey is limited to a max of 12 characters. If you declare a function name longer than 12 characters the function will not be registered.\nSo, keep in mind that you can only have four functions, and, if any of the function names are too long, they won't even get registered. So, the function not found error? While not useful, it's at least technically accurate – since my function name was too long, it didn't get truncated, it was simply never registered.\nIt was my understanding that the functions were registered somehow with the cloud, so the cloud understood what is exposed by the device and could act upon the requests coming through. Apparently when you use a function name that's too long, the device never even attempts to register it with the cloud. That's why the server returns function not found, it's because the function doesn't even exist as far as it's concerned and it doesn't know what else to do.\nNow, I suggested to the Particle community that the cloud could tell that the name was too long and not even try to look for it, instead returning a useful error message that the function name was too long. That suggestion was shot down by a varying degree of “you're not understanding” or “why would we want to deal with something the developer should have done better” attitude from the community, so don't expect this to ever be fixed by them. Interesting attitude for a hacker community.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Configuring a Node Express Environment on the Raspberry Pi",
  "date":"Mon Feb 15 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1455580800,
  "url":"/posts/2016/configuring-a-node-express-environment-on-the-raspberry-pi/",
  "content":"As I posted last week, I'm working on a project on the Raspberry Pi. As I'm not a Python developer, I thought I'd write my server code using Node. My previous post was about how I configured my WebStorm instance so I could code my JavaScript on my PC and publish it on the Raspberry Pi. Once I had that working, I started testing my app on the Pi, and that's when I started running into problems. It took me a little while to figure this one out, so I thought I'd write about it here in case others have the same problem.\nAs any hardware developer does, before I started, I made sure my Pi had the latest version of Raspian, the default OS for the Pi. In this case, I grabbed the latest version of Raspian from https://raspberrypi.org/downloads/raspbian/. In this case, it's Raspian Jessie (February 2016) as shown in Figure 1.\n\nFigure 1 – Raspian Download Page\nI burned the OS to a memory card, inserted it in the device and booted it up. After it booted, I opened a terminal window and checked the node version. Raspian Jessie ships with Node 0.10, which is pretty old. So, before I went any further, I knew I had to update my Node installation. I checked and npm wasn't installed as well, so I had to do that installation as well.\nFortunately, the folks at Adafruit published some instructions on how to upgrade node on the Pi; you can find the instructions here: https://learn.adafruit.com/node-embedded-development/installing-node-dot-js. Basically, all you have to do is execute the following commands in a terminal window to update node:\n\nWhen you're done, execute the following command to check the version:\n\nIt should return something like v0.12.0 or greater. OK, at this point, I know I'm running a newer version of Node than came with the latest version of Raspian.\nNow, I knew that interacting with the Pi's GPIO ports was a little different, so I knew I'd need a library to make this easier in Node. One of the articles I found mentioned a library called rpi-gpio (https://npmjs.com/package/rpi-gpio), so I thought I'd give it a try.\nI opened a terminal window and tried to install rpi-gpio using the following command:\n\nUnfortunately, the installation failed every time I tried to install it. In the npm log, I found the following:\n\nApparently, the build process failed. Not sure what to do, I looked at the author's GitHub account (https://github.com/JamesBarwell/rpi-gpio.js) and found a recent issue that was similar to my problem (https://github.com/JamesBarwell/rpi-gpio.js/issues/33). There wasn't an immediate solution provided, but one helpful (sarcasm) visitor suggested looking at the readme at https://github.com/JamesBarwell/rpi-gpio.js/blob/master/README.md#dependency. Apparently the version of gcc is a problem with Raspian.\nI quickly took a look, and the version I was running was much, much different than rpi-gpio expected. A quick pointer to https://github.com/fivdi/onoff/wiki/Node.js-v4-and-native-addons provided me with the instructions to install the latest version of gcc on the Pi.\nUnfortunately, after the gcc update, it still didn't work. On a hunch, I restarted the Pi and suddenly it worked, the rpi-gpio module installed successfully and I was all ready to go (at least until the next problem pops up).\nI just have one question for you: why does everything have to be so hard?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Xmas Jam 2015 Epic Failure",
  "date":"Sun Feb 14 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1455494400,
  "url":"/posts/2016/xmas-jam-2015-epic-failure/",
  "content":"I'm a huge fan of everything Warren Haynes does; a friend of mine introduced me to Gov't Mule many, many years ago and since then I've purchased every one of his CDs and attended every concert I can (solo, Mule, Allman Brothers).\nWhen I moved to North Carolina, I was surprised to learn that he has a yearly charity concert called the Christmas Jam just a few hours' drive away. I quickly bought tickets, found someone to watch the kids and my wife and I headed off to the show. We loved it.\nIn case you haven't heard about this show before, here's a little background. Warren is from Asheville, and every year he hosts a benefit concert for Habitat for Humanity. A bunch of bands come into town and essentially this show takes over the town. The show starts at 7 PM or so and runs until every band has had a chance to play. The first time we attended, Greg Allman started playing at 2 – we watched half of his show and went to bed (couldn't stay up any longer) and I don't know how much longer the show went on.\nThe show's amazing and donates a bunch of money to the charity, but there are a lot of flaws in its execution, and that's what this article is about.\nGeneral Implementation Flaws\nHere are some of the general purpose issues with the implementation of the concert.\nGeneral Seating\nFor some bizarre reason, the concert promoters decided to setup this event as general seating. What this means is that if you buy a ticket to the show, there's no guarantee you'll have someplace to sit. Yep, first come, first served and it's a freaking nightmare.\nSee, they sell out the show, so there's multiple thousands of people there trying to find a place to sit. Now, if you want to stand for 8 hours or so, this isn't a problem as you can come in and go right to the floor and stand in front of the stage all night listening to the bands. I'm an old guy, so I can no longer stand for hours at a time, so that option isn't good for me.\nSo what happens, for those that aren't content to stand on the floor (like me), is that most people get there early and stake out a place to sit in the stands. This isn't that big of a deal except that when people stake out their seats, people generally leave one seat open on either side of them. Right? You don't want to be crushed up against someone else all night (and it is a loooong night), so when you mark your seats, you make sure there's space between you and the couple or group next to you. The problem with this is that since this is a sold out show, there are a LOT of people looking for seats. With the extra seats being open, what this means is that for every group of two people, three seats are consumed. Do the math, that means that a full 33% of the seats are sitting empty, but, don't forget that it's a sold out show. It's a freaking nightmare.\nUnless you're a party of one, there's no way you're finding two seats open anywhere within the arena. If you're two or more people, which most are, the only way you're getting a seat is if you get there reeeeeally early or if you are willing to cajole and push people into shifting around in a particular row to open up enough seats for you. Did I mention it's a freaking nightmare?\nThey could sell assigned seats and fix this entire problem, but every year there are hundreds or potentially thousands of folks wandering through the arena looking for a place to sit.\nVIP Tickets\nNow, when I first attended the show, there was an option to purchase VIP tickets at a slightly increased cost. I don't remember how much it was, but it wasn't that much, and it made it much easier to attend the show. With VIP tickets, there's a dedicated area on the floor where you can stand. It's off to the right, so you're not near the middle of the stage, but you can still see and hear everything well. With the VIP standing area, it's easier to come and go and still have a good view. I would argue that regular seats are actually better since you're closer to the middle of the stage, but if you want to be close, you can't get very close with regular tickets.\nAnother benefit of the VIP ticket is VIP Seating – the arena marks off a couple of sections for VIP ticket holders, and it's easier to move between the seats and the floor. Not much easier as the same seating problem that applies to the general ticket holders apply to VIP ticket holders. 33% of the seats are empty between the groups.\nAnyway, this was a great option the first year we attended the show, but the very next year they increased the VIP ticket price by about 6 times. Were it was a reasonable bump to get VIP tickets my first year, the next year it was hundreds of dollars more (I think it was about $300 more), so really not worth it.\nWhat Went Ghastly Wrong this year\nSo, with that background in mind, what could have been so horrible about this year's show to warrant this article. Let me count the ways…\nJoe Bonamassa No-show\nWe decided after that first year that we would only go again if we had VIP tickets (it was too much of a b",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "PhoneGap Essentials Web Site Retired",
  "date":"Sun Feb 14 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1455494400,
  "url":"/posts/2016/phonegap-essentials-web-site-retired/",
  "content":"\nThe PhoneGap Essentials web site was retired today. The site was a repository of information about my PhoneGap Essentials book. I retired the site because the book was published more than three years ago and is woefully outdated. The book targeted PhoneGap 2 and since then many things have changed. PhoneGap was changed to Apache Cordova the PhoneGap became Adobe's distribution of Apache Cordova (with some extra things added). As Apache Cordova and PhoneGap are both now at version 6, it didn't seem appropriate to maintain a site dealing with technologies 4 versions back.\nSince the book was published, I have published multiple updates to the book. Apache Cordova 3 Programming was an update to the first half of PhoneGap Essentials. The second half of PhoneGap Essentials was later refreshed in a new book called Apache Cordova API Cookbook. So, with both of those books, you have an update that covers the newer version plus jumps from 300 pages to about 500 pages.\nThen, when Apache Cordova 4 came out, I updated the Apache Cordova 3 Programming book for Apache Cordova 4 (which also covered PhoneGap 4) in a new book called Apache Cordova 4 Programming. With this book in place and coupled with the Apache Cordova API Cookbook, you now have about 800 pages of material on the newer version of Apache Cordova/Adobe PhoneGap.\nSo, if you're looking for PhoneGap Essentials, you will be better served by Apache Cordova 4 Programming and Apache Cordova API Cookbook.\nIf you have to have information on PhoneGap Essentials, you'll find all of the book's code on my GitHub page at https://github.com/johnwargo/phonegap-essentials-code.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "BlackBerry Development Fundamentals Website Retired",
  "date":"Sun Feb 14 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1455494400,
  "url":"/posts/2016/blackberry-development-fundamentals-website-retired/",
  "content":"\nThe website for my BlackBerry Development Fundamentals was retired today. The book was published back in 2009 and focused on BlackBerry 6 (or was it 7? I can't remember it's been so long) development. At the time, BlackBerry apps were written in Java, but now, with BlackBerry 10, BlackBerry devices run a completely different OS and apps are written in C. BlackBerry's newest device is an Android device, so BlackBerry as a development platform is essentially dead.\nIf you have a copy of the book and you're working through some code for a very old BlackBerry device, you can find all of the sample code from the book on my GitHub page at https://github.com/johnwargo/blackberry-development-fundamentals-code.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "WebStorm Development on the Raspberry Pi",
  "date":"Tue Feb 09 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1455062400,
  "url":"/posts/2016/webstorm-development-on-the-raspberry-pi/",
  "content":"I've been working on a Particle Photon-powered garage door opener project with my son; I'd found an example project online somewhere (I can't remember where, otherwise I'd post a link here) and looked pretty interesting. I, of course, modified it and put my own twist on the project. I'll write about the project once it's completed. The project's pretty simple and it's all ready to assemble (plus the code is all written).\nI came up with a few features I wanted for the opener that I couldn't implement on the Photon, so I decided to do a V2 on the Raspberry Pi. I've got the hardware all figured out and I wanted to create a node-based server process running on the Pi to control everything. I love working with the Pi, but I honestly don't want to write code on it. The editors I'm comfortable with aren't compatible and the system's just not fast enough for the dev stuff I want to do. So, for this server project, I started thinking of how I could use my PC to code everything, but also maintain a quick and easy way to publish code to the Pi for execution and testing.\nMy JavaScript/Node editor of choice is WebStorm from JetBrains, so my plan was to code in WebStorm then transmit the files to the Pi. Once that was in place, I needed a quick way to restart my code so the new version of the server was available for testing. One thought was to use GitHub as an intermediary for this, but that seemed slow and clunky. Next I figured I could use FTP to post the files to the Pi. Thinking that manually FTPing the files to the Pi would be a pain, I started looking at what WebStorm could do. It turns out that WebStorm supports SSH, so I was able to quickly setup a publishing target in WebStorm that allowed me to easily deploy changes to the Pi.\nWhat follows are instructions on how to setup WebStorm to publish code directly to the Pi.\nImplementation – Enabling SSH\nThe first step in the process is to enable SSH on the Pi. It's fairly easy to do this, simply open the Raspberry Pi Configuration utility (open the Pi menu and select Preferences, then Raspberry Pi Configuration). In the dialog that appears (Figure 1), select the Interfaces tab then enable SSH as shown in the figure. When you click the OK button, the Pi will reboot with SSH enabled.\n\nFigure 1 – Raspberry Pi Configuration Application Interfaces Tab\nThe next thing you need to do is figure out how your desktop development environment will connect to the Pi. WebStorm needs to know how to reach the Pi; you could enable DNS and use the Pi's name to connect to it, but that's more complicated than I wanted for this project. Instead, I decided to connect to the Pi using the device's IP address. There are several ways to determine the Pi's IP address. A quick look at the Pi documentation told me I could use the following command to determine the IP address:\n\nSo, I opened a terminal window on the Pi and typed in the command and received the results shown in Figure 2. The first time I did this (OK, it was a couple of times) I didn't get the results I wanted. I'd type in the command, but I'd get back an IP address of 127.0.1.1 which is a local address (only accessible from the PI) and something that wouldn't work for me. I finally figured out the problem, I used a lower case i and that got me completely different results.\n\nFigure 2 – Using the hostname command to determine the Pi IP address\nAnother way to get the IP address is to execute the following terminal command:\n\nWith this command, you get the results shown in Figure 3.\n\nFigure 3 – Using the ifconfig command to determine the PI IP address\nUsing either approach, I quickly determined my device's IP address (192.168.1.92). With that in place, I'm ready to configure WebStorm.\nConfiguring WebStorm\nNow that I know how to reach my Pi and the SSH software is installed, it's time to configure my WebStorm project to publish my code to it. In WebStorm, open the Tools menu, select Deployment then Configuration; you should see a dialog similar to the one shown in Figure 4.\n\nFigure 4 – Configuring a Connection in WebStorm\nThe first thing you'll want to do is click the green plus sign in the upper-left corner of the dialog. By clicking on it, you're instructing WebStorm to create a new connection. When the new connection appears (it will take up the right side of the dialog as shown in the figure), do the following:\n\nSet the connection type to SFTP as shown in the figure.\nSpecify the Pi's IP address as the SFTP host.\nLeave port alone; port 22 is the default port for SSH and the Raspberry Pi will use it by default.\nFor Root Path, you can type in the full path pointing to the Pi user's home folder if you know what it is. I didn't know, so I clicked the Autodetect button and it filled it in for me.\nSpecify the User name defined on the Pi. The default user name is “pi” and the default password is “raspberry” – if you've changed the default user settings on the Pi, make sure you enter the correct values here. Set Auth type to Password as shown ",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "What's Wrong With Trolling",
  "date":"Sun Feb 07 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1454889600,
  "url":"/posts/2016/whats-wrong-with-trolling/",
  "content":"My publisher recently asked me for some content to use to help promote my latest books, so I spent some time during the holidays writing a couple of articles for their website. I recently received one of the articles back from the editor and I was struck by the absurdity of one of the comments in the file. This post is my response to that absurdity.\nWhen I get a few spare moments, I look through the Cordova/PhoneGap questions on Google Group or Stack Overflow. Whenever I do, I usually find one or two that I can answer without too much work, so I give it a shot. In my most recent article about Cordova, I wrote the following:\n“For many years now, I've been trolling the PhoneGap Google Groups and Stack Overflow Cordova sites, trying to answer what questions I can.”\nIn response to this, the editor wrote the following:\n\n“Can you think of a verb that doesn't resemble troll, since that word is also used to describe the abusive activity of online jerks?”\n\nAs I'm describing a scenario where I'm putting a hook in the water and driving around in my boat looking for fish, I was pretty happy with my choice of trolling in this case. That is, after all, the definition (source https://merriam-webster.com/dictionary/troll):\n\nTo fish with a hook and line that you pull through the water\nTo search for or try to get (something)\nTo search through (something)\n\nSometimes a word is just a word and the classic definition of the word…simply…works. In this case, there's trolling for fish and, the other, bad, Internet Troll. In this case, I'm pretty sure my context is clear; as you read the sentence, does it feel to you that I'm announcing to the world that I monitor Stack Overflow and Google Groups looking for people to attack verbally? Or, more reasonably, did I intend to mean that I'm, as per the Merriam Webster dictionary definition above, searching through something?\nWe shouldn't be afraid to use words simply because of one, unofficial, interpretation of the word. The urban dictionary, for example, completely ignores the actual definition of the word and instead leads with the bad Internet Troll interpretation of the word. I bet that many people don't actually know the true meaning of troll; the Urban Dictionary's manipulation of the definition doesn't help either.\nWe have to stop looking for things to be offended about; people are way, way too sensitive nowadays and it's getting a little ridiculous. As George Carlin famously said: “There are bad thoughts, bad intentions, and words.” I'd like to amend that to the following: “There are bad thoughts, bad intentions, actions and words.” Judge me on my actions or the reasonable assessment of my words; not the potential, unreasonable interpretation of a word. Reasonable people will likely assume the least offensive meaning of my use of trolling until I prove otherwise.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "The Maker's Guide to the Zombie Apocalypse",
  "date":"Sun Jan 17 2016 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1453075200,
  "url":"/posts/2016/makers-guide-to-the-zombie-apocalypse/",
  "content":"I recently received a copy of Simon Monk's The Maker's Guide to the Zombie Apocalypse. I'd read several of Simon's books (Programming the BeagleBone Black and Make: Getting Started with the Photon). I've enjoyed his books, and they've helped me learn how to work with the Photon and BeagleBone Black.\n\nI travel a lot and when I'm trying to learn something, I prefer to pick up a book and work through the book step by step. Online documentation is OK, especially when you're trying to find a quick fix to something, but I find that books are better at the overall learning you need when you first start working with a hardware device, developer tool or programming language. There's something about the structure of a book vs. poking around in product documentation that makes it easier for me to learn from a book.\nThis book is different – instead of working with a specific hardware device, he's picked a theme for this one and targeted all of the book's projects to that theme. In this case, it's all about some projects you can do that will help you survive the Zombie Apocalypse (ZA). Overall, he's done a good job in selecting useful projects and connecting them well with the theme. The good news is that even though he's working with a theme, and having some fun with the whole Zombie aspect of it, he doesn't overdo it. The ZA attitude and the jokes that accompany it are fun and not overdone. I especially liked the web cam example image that included a Zombie in it – a nice and fun touch.\nThe good thing about this themed approach is that he's crafted a series of useful projects then tied them together with a single management console. Each project can be built separately, but when you follow the theme and get them all working together through the console, you get a feel for how more complicated projects can work.\nSince he's focusing on a series of projects and not a specific hardware device, you get to see how to implement projects on different hardware platforms (Most projects are on the Arduino, but the Raspberry Pi shows up as well).\nUnfortunately, his parts lists don't take into account that you might not be adding a particular project to another existing project that already has some parts. I found myself looking at the shopping list and thinking that things were missing only to discover later that he's expecting this particular project to be added to another. I would have preferred a complete list of parts that were somehow marked to indicate “You may already have this part if you're adding this to that other project.” It's not a big deal, but it did cause me some pause as I tried to figure out which parts were needed to complete the whole project.\nThe thing I liked the most about this book compared to the others I'd read is the length of the book. Since he wasn't doing a quick hit on a specific hardware device, he spent more time (pages) covering the background material in detail before showing how to make the report. I especially liked the chapter on survival tips for the ZA: Chapter 1 – Apocalypse Basics. In this chapter he covers some basic survival requirements before jumping into the skills you need to make the projects. In the second chapter, he talks about how to generate electricity and provides a lot of good background about electricity and battery life. The value of this for many readers will be when they're trying to build something with similar (but different parts); the material he provides makes it easy for the reader to figure out how his stuff will work compared to what Monk shows in the book. He did a really good job showing how to make use of the flash in a pile of discarded (empty) disposable cameras.\nOf all the microcontroller projects book I've read (and I've read a bunch), this book had more practical material (background and project) than most others. There are real world applications for each of the projects described herein. Additionally, the none of the projects were that hard, I knew I had the skills for each. I'm looking forward to see what he does next.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Arduino",
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Outlook Populating Country Only in Contact",
  "date":"Tue Oct 06 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1444176000,
  "url":"/posts/2015/outlook-populating-country-only-in-contact/",
  "content":"For years, I've had this problem in Microsoft Outlook where Outlook will populate only the country field for select contacts. I've never done it purposefully, but somehow either because of some weird sync process or other reason, I had a bunch of contacts with no address, only a country set for them.\n\nFigure 1 – Michael Palin Contact Card (NOT his real contact information)\nAnyway, this has been bugging me for some time and I've been too lazy to fix this manually. So, with all the Outlook integration code I've been doing lately, I decided I'd write an app that whacks the Country fields value (there are 4 of them: mailing, home, work and other) from every Outlook contact.\nI've posted the Delphi project code to GitHub. The app basically opens a memo field and processes all of the contact records, blanking out the country if it's 'United States of America'. I got the code working then cleaned up my contact list.\nThought about it a bit and realized that I could have done a better job with the code. I made separate blocks of code to check each country field individually, turn out that there isn't (that I could find) a way to retrieve a contact record field value by name, so I don't think there's a better way to do this. Also, whenever the app whacks a country field, it saves the record. I could have easily tracked whether a change was made and save only once, but I didn't.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Outlook",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Accessing Outlook Categories Using Delphi",
  "date":"Sat Sep 26 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1443312000,
  "url":"/posts/2015/accessing-outlook-categories-using-delphi/",
  "content":"As I mentioned in my previous post, I'm helping a friend with some Microsoft Outlook integration and came across the need to access the list of meeting and email categories defined within Outlook. Microsoft has done a great job of documenting the object model for Outlook, so it's quick work in Delphi to open an OLE connection to Outlook and get a listing of the Categories. The code's below, but I also posted the complete project to GitHub.\nHere's the code:\n\nThe output object is a TMemo component on the app's main form, so it is used to list all of the categories when the app initializes. The app doesn't do anything with the categories, this is just an example of how to retrieve them.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Outlook",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Deleting Empty Outlook Appointments",
  "date":"Fri Sep 25 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1443225600,
  "url":"/posts/2015/deleting-empty-outlook-appointments/",
  "content":"Until recently, I've always kept my main set of contacts on my personal mobile device and used Exchange ActiveSync to synchronize it with my mobile device. When I joined Forrester, I decided to keep my work stuff separate from my personal stuff. So, rather than have all of my personal contacts available to me while at work, I let my work account sync my work PIM data to my device through its normal means and used a separate process to sync my person PIM data to my device as well.\nSince I carry an Android device, I looked around and found an open source solution called Go Contact Sync Mod (https://googlesyncmod.sourceforge.net/) that works pretty well. I could have the sync run automatically, but for now I'm running it manually. One of the things I noticed when I run it is that it was showing an error indicating that it had found empty calendar entries in Outlook. I didn't know I had empty calendar entries nor did I know you could create empty calendar entries, but apparently my pst file had a bunch of them.\nI looked around for a while and didn't find a solution for deleting those empty entries, and I couldn't 'see' them in Outlook, so I decided to write some code to solve the problem. I'd been helping a friend with some Outlook automation, so I had the basis of what I needed to make this work. I'm a big Delphi developer, although I'm pretty upset with Embarcadero right now, so it gave me a chance to dust off my Delphi skills and write some code.\nI'm not going to go through everything here, but I've posted the code to GitHub at https://github.com/johnwargo/Kill-Empty-Outlook-Calendar-Entries. Basically you can open the project in Delphi then build and run it, or you can use the pre-built executables I've included in the repository. Enjoy!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Outlook",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "RasPiO Duino",
  "date":"Sat Aug 15 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1439683200,
  "url":"/posts/2015/raspio-duino/",
  "content":"My son and I finished assembling our Million Color Flashlight https://makezine.com/projects/million-color-hsl-flashlight/ on Friday night, so I was cleaning up my workshop last night and decided to assemble something I had lying around I've been sponsoring different kickstarter projects for Arduino-based products and a kit I had in my shop was for the RasPiO Duino, an Arduino prototyping board you program by attaching it directly to the GPIO pins on a Raspberry Pi.\nHere it is all assembled, it was fun to practice my soldering skills:\n\nI think this would be an excellent addition to any elementary or middle school class on microcontrollers. It allows someone to learn how to program the Arduino with limited computer hardware (just a $35US Raspberry Pi, keyboard, mouse and monitor). I'm going to see if I can come up with an interesting project for this thing soon.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Apps that Act on my Behalf",
  "date":"Thu Aug 13 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1439510400,
  "url":"/posts/2015/apps-that-act-on-my-behalf/",
  "content":"The whole &quot;There's an app for that&quot; was fun for a while, but now it's time for us to be able to do things without needing an app. A good example of an early implementation of this is with Google Now where it automatically figures out that I've parked my car and gives me directions back to it. With no action on my part. Here's an example:\n\nThe phone new it was connected to my car as I was driving, it also knows where my home is and that I'm not at it. So it figures that I probably want to be able to get back to my car once I need to go home and simply takes care of that for me.\nThat's awesome, useful technology that requires no action on my part. That's smart computing if you ask me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "The Challenge Getting an Amazon Echo",
  "date":"Tue May 19 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1432080000,
  "url":"/posts/2015/the-challenge-getting-an-amazon-echo/",
  "content":"For years I've wanted to be able to use voice to interact with the systems around me. I want to be able to talk to my computer as I'm working and in the house I want to be able to interact with everything in my house as I do things. I'm spoiled, I guess, by all of the Science Fiction books and stories I've read throughout the years.\nI first got interested in this when I heard about Wildfire, a virtual assistant that ran within your computer. What was interesting about Wildfire (as I understand it) was that it was essentially a PC on a card that sat inside your PC and processed all voice inputs then acted on them. It was expensive and essentially required that you had two PC's, one inside the other.\nI've waited and waited and waited for a system that I could just… interact with. I tried Dragon Naturally Speaking (didn't work for me) and constantly watched the industry for my perfect solution.\nMuch later, we got Google Now and Siri, both very capable voice interaction systems. They're awesome and very useful, but this isn't something I want on my mobile device, I want it in my surroundings – everywhere. Anyway, with these smartphone-controlled systems, they work great and save me a lot of hassle when I need to get something done and I'm tied up.\nThe problem is that I have to dig my phone out of my pocket to use it and that's not always possible. I carry my phone with me when I'm away from the house, but generally it's on my desk during the day (while I'm working) and still there when I go 'home' at the end of the day. I'm old, I didn't grow up keeping my phone with me at all times. Also, having worked at BlackBerry and being constantly connected taught me that I should put it down every night and ignore anything on it until the morning. I laugh when people call my mobile at night instead of just using my home number – not likely to catch me on the mobile at night unless I'm out of the house.\nAnother aspect of this is that I ultimately needed something that anyone in my family could use at any time. My wife doesn't carry her phone around with her when she's in the house either, and we have two children that don't have mobile phones, so we needed something that went with the house, not a person.\nAnyway, this is a post about the Amazon Echo so I'd better get to it, right?\nLast November, Amazon announced the Amazon Echo – a voice interactive system that sits on a counter or desk and waits to act upon your every command. Simply say &quot;Alexa&quot; (or &quot;Echo&quot;) and she'll respond and try to deliver an answer to any question you give her or act upon any command she understands. I LOVED the idea and immediately (like 30 minutes after the announcement) requested access.\nI waited. And continued to wait. I waited a really long time (more than a month) and never heard anything back from them. Disappointed.\nAbout a month later, I had some family in town and mentioned the Echo to my brother. He immediately hopped online and requested his Echo. I assumed, wrongly, that since I got on the list day-one, that I'd get my Echo WAY before he did, so I didn't worry about letting him in on my little Echo secret.\nWrong! He got his Echo about a week or so later. Ugh!\nApparently, much to my chagrin, Amazon RANDOMLY selected the people who got the early Echos. I'm not sure they told me that when I requested mine, but who reads those disclaimers anyway, right? So, unlike most any get your new product process and most any product ordering scenario, Amazon didn't deal with requests on a FIFO basis, they simply randomly pulled names out and sent them their Echo's.\nThis was really frustrating. I wanted something like the Echo for so long and I was finally going to get my chance, but there was pretty much no way for me to get one. Sigh.\nI started surveying my friends and found out that many other people got theirs – most having requested theirs after I requested mine.\nSo, like any able bodied American, I started complaining. I emailed Amazon Customer Service and was politely told that it was a random selection process. Frustrating. I started tweeting about it, making as public of a scene as I could without tarnishing my name to much and within about a week or so, Amazon sent me an email with information that would 'allow' me to order an Echo. I plunked down my order as fast as I could only to learn that my Echo wouldn't ship for months. Everybody else requested theirs, got an email allowing them to order very quickly then got their Echo in no time. For me, I had to wait months for an invite then another set of months to actually receive it.\nNot really handled very well by Amazon.\nAnyway, I finally got my Echo and I LOVE it. I'll write more about it here when I get a chance.\nAs much as I'm complaining about Amazon, I understand why they did what they wanted. I'm pretty sure they made me wait to get an Echo simply because I requested one as soon as I learned about it. When testing mass market devices like this, you want some early a",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Where I Landed",
  "date":"Wed May 06 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430956800,
  "url":"/posts/2015/where-i-landed/",
  "content":"As you may have heard, my position at SAP was eliminated back in March. Out of the options I had before me, I accepted a position at Forrester Research as a Principal Analyst in the Application Development &amp; Delivery area. I'll be one of three folks on the team focusing on mobile development plus I'll stick my nose into other areas of AD&amp;D as I get comfortable.\nMy new position will have an impact on what I will be able to publish here. Anything related Forrester's business will be published in formal papers or posted to my Forrester Analyst Blog (I'll post a link here once I get it setup). I will be able to talk a bit here about the tools and frameworks I'm playing with. I'll also be able to cover some technical topics here that are too deep for the traditional analyst fare. We'll see what happens; I want to continue to write here, but I need to be sure it's the right content.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "The Stupidity of Security Questions",
  "date":"Sat May 02 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430611200,
  "url":"/posts/2015/the-stupidity-of-security-questions/",
  "content":"Today I thought that Mother's Day was tomorrow. My wife informed me that it's not tomorrow, it's next week. Dodged a bullet there. I've been experimenting with the Echo, trying to understand what she understands and what she doesn't. Did you know you can get her to stop playing music by telling her 'Shutup b#tch'? That surprised me, but at the same time, didn't. Anyway, I asked her when Mother's Day was and she told me it was the second Sunday in May. I didn't know that, so it was nice to have that detail. I really wanted the date, so I asked her &quot;What date is the second Sunday in May&quot;. She didn't understand my query for some reason. As you can see, I didn't ask her what I really wanted to know, so my fault for her getting it wrong. What I really wanted to know was the date for Mother's Day, perhaps I should have asked her that.\nI was looking at the echo app a little while later and noticed that the app was showing me what she heard and asking whether she got it right. What she heard was &quot;What is the second Sunday in Maine?&quot; Close, but wrong. I indicated in the app that she got it wrong and once I did that, a pop-up, well, popped-up asking if I wanted to provide more feedback, so I said yes and entered what I was trying to search for in the input field. When I clicked Submit (or whatever it was) apparently it sent an email to Amazon with my feedback.\nCool stuff, get me to help them tune her algorithm. It's Google Voice all over again.\nWhat happened next is where it got…weird. A few minutes later, I get a call from an Amazon Echo support person wanting to talk with me about my issue. That's cool; not what I expected, but cool.\nAs I started to talk to the guy, he said he couldn't talk to me until I confirmed the answers to some security questions. What? You called me and you want ME to confirm the answers to some security questions? Nope, no way – refuse to do it.\nIt's a closed loop, from the Amazon Echo app to Amazon support all the way back to me. What value is there in me proving that I'm who I say I am? You called me, right? I don't have an issue when I call them and they need my security questions answered in order for me to prove I'm me. But when you call me, I really don't feel inclined to confirm to you I'm who I say I am.\nYou called the number you have for me in your system and I answered. I'm not trying to make any purchases or change anything on the account, you're merely calling me about some feedback I provided you on the accuracy of the Amazon Echo's text recognition algorithms. No need for security questions in this case.\nAnyway, just on principal, I refused to answer the security questions and explained why (that it was simply a matter of principal and I generally refuse to do stupid things unless I have no other choice). After I hung up, I thought about something. Answering the security questions IS a security issue – what if my email from the Echo app was intercepted (I can't understand why Amazon would use email for this and not a secure HTTPS connection through the app) and the phone call was a Phishing attempt to get my answers to my security questions so they can use them to impersonate me? Nope, not doing it.\nWhat do you think? Am I crazy? Stupid?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Is Amazon Listening",
  "date":"Sat May 02 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430611200,
  "url":"/posts/2015/is-amazon-listening/",
  "content":"I've been having a conversation lately with a former colleague about voice control of physical devices. As I mentioned yesterday, I purchased an Amazon Echo and just love the way it's transformed my kitchen. My family is playing music, setting timers, checking the weather and adding fun and interesting things to the shopping list.\nI'm struggling a bit because I want to be able to control another device in my house using the Echo. My former colleague works for the company that makes that other device and I've been trying to understand their plans for either integration with the Echo or direct voice recognition in their device.\nI initially thought that I wanted the Echo to control everything, but then I realized that I will probably only have an Echo in my kitchen and I have other products all throughout the house that I want to be able to talk to (thermostats, streaming music players, lights, locks and so on). While I really don't want different voice control systems to learn the syntax for, I realize that there's likely not going to be a way to have a single source of control unless I do put an Echo in every room. At $199 each, that would be a challenge.\nAnyway, during these conversations with my former colleague, it became clear that there are privacy some concerns about the Echo. In my mind, the Echo is sitting there idly listening for its command word, and only then does it wake up and listen to what else you've said. It's possible that the Echo is listening to everything we say, but is that really something that's important to Amazon?\nThe amount of data being processed and uploaded to Amazon would be staggering. Now, they could be listening for key phrases, keywords as it were, and sending them up, but again, that could be a seriously large amount of data as well.\nI think of bigger concern is that someone could hack the Echo and then start listening to everything we say. The government would be a good candidate for that as would anyone in the industrial espionage area, but is this really something we need to actually worry about? I think the answer to that is both no and yes.\nNo, I don't think Amazon is listening to everything we say. Well, that's not correct, the Echo IS listening to everything we say, but it's not 'using' any of it until after it hears someone say 'Alexa.' However, I really don't have any concrete proof of that – it's only what I figured out myself as I thought about how the Echo works. I don't think we need to worry about this as I trust Amazon to do the right thing. However, I should probably assume nothing and actually find out what they do so that I can be better prepared.\nYes, I think we should worry about this. Just because you're paranoid doesn't mean someone's not out to get you. We already have voice control in Google Now and Siri and my 8-year old automobile has a voice control module although the car is not Internet connected. However, we are about to start putting voice control devices all throughout the house and eventually everywhere else.\nI've read a few books about the NSA and what Edward Snowden did, so I'd be surprised if the Government didn't start listening to that stuff as well (looking for keywords of course, then digging deeper). Again, I'm not paranoid, but I do believe in having reasonable expectations. If the NSA is really looking at all of our Facebook and Twitter posts, and listening to our phone calls, then how much of a stretch is it to imagine them hacking into our houses and listening through these voice-control devices?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Becoming an App Guy",
  "date":"Thu Apr 30 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430438400,
  "url":"/posts/2015/becoming-an-app-guy/",
  "content":"It seems like I'm becoming more of an app guy lately. It was an interesting realization for me as it's surprising that I've been in mobile for 10 years, but just now seem to be getting into apps.\nOf course, spending some time thinking about it, it's not surprising.\nMy entry into mobile was through BlackBerry; I was a Technical Manager, Applications – meaning that I helped customers understand how they could build apps for the BlackBerry platform. I was a developer supporting developers and, at the time, not much was available for consumers, it was all enterprise apps. Since enterprise required having access to back-end enterprise data, and I didn't use any enterprise apps at the time, not much was available to me.\nNext I headed over to BoxTone (now part of Good Technologies) and was focusing on BlackBerry server performance and BlackBerry device performance. Not many apps for me to rely upon. That and I was a BlackBerry guy as the world abandoned BlackBerry, so even less interest in apps.\nAt AT&amp;T, I was part of a sales team selling mobile application platforms. These were Mobile Enterprise Application Platforms (MEAP) and Mobile Consumer Application Platforms (MCAP) which was all eventually renamed to Mobile Application Development Platforms (MADP). In my focus on platforms, I knew how to build apps for the Antenna, Pyxis (now Verivo) and Kony platforms, but was so busy with development stuff, that I really didn't use a lot of apps. That and working for a carrier, I was constantly switching phones; switching between BlackBerry, Android, iOS and Windows phones – there was really no way for me to use a big app catalog with my device in flux.\nAt this point, I started using and writing about Apache Cordova and Adobe PhoneGap and therefore had a ton of sample hybrid apps on my devices, but none of them helped me much in my day to day activities.\nNext was SAP and I was fortunate enough to be a product manager for part of a mobile development SDK and again focused on helping enterprises build their mobile apps. For a while, I stayed on BlackBerry, but eventually switched to Android. I started using more and more Android apps, but ultimately I stopped traveling so had less need for apps as I moved around.\nDuring my transition from SAP, I started having trouble with my Android phone, so I activated a Windows Phone device that Microsoft was kind enough to give me as I worked on my last book. I struggled a bit with the device since some of the apps I found to be critical (like the Sonos app and the Amazon Echo app) weren't available on Windows Phone. Time to switch back to Android.\nI'm getting ready to make a BIG career change and because the company I'll be working with supports a bring your own device (BYOD) environment, I had to buy my very first smartphone (the first one I ever paid for) and my second iPad. I've been reading some books lately on mobile apps and I started researching more apps and loading them on my device. I think the quality and quantity of apps available to consumers is great. I think the separate app for each activity or relationship is a flawed approach, but I'm enjoying getting all of these apps and making them a part of my daily routine.\nAlready, I'm finding myself spending more and more time with the following apps:\n\nSonos: controlling the music that surrounds me\nPandora: when I want to listen to music when I only have my tablet or smartphone near\nZinio: Unfortunately, a few of the publications I read are ONLY available in electronic format; I HATE that.\nPocket\nFlipboard: I LOVE flipboard, that's how I get all my news now\nEvernote\nAmazon\nBanking and Credit card apps: direct deposit is way overdue.\nDropbox\nGoogle Drive and apps\n\nI used to hate the Zinio app, but it's gotten better although it's still flawed in a great many ways, at least it works most of the time (which is an improvement).\nThere's a bunch more, but you see my point. So many aspects of my day are enhanced through the information provided by these apps. Notice that I'm not playing games – too much other stuff to do.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Apache Cordova 4 Programming Now Available",
  "date":"Wed Apr 29 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430352000,
  "url":"/posts/2015/apache-cordova-4-programming-now-available/",
  "content":"\nMy latest book, Apache Cordova 4 Programming , is now available in stores. This is my 7th book overall and my 4th book on Apache Cordova/Adobe PhoneGap.\nThe book is written for mobile developers who want to learn about Apache Cordova 4. If you're brand new to Cordova, then this book will be just what you need to get started. If you're experienced with an older version of Cordova, this book can act as a refresher plus will show you in detail how to use all of the new stuff that's in Cordova 4. You will need to have at least some experience with mobile development to directly benefit from this book. The target audience could be existing web developers who want to get into mobile development, but much of the needed native mobile development background just isn't in here. Sorry!\nWhat you'll find in the book:\n\nLots of detailed information about Apache Cordova, what it does, how it works and how to use the available tools and APIs\nLots of examples and code; for even more code, be sure to check out my Apache Cordova API Cookbook\n\nWhat you won't find in this book:\n\nMobile web development and mobile development topics; this is a book about Apache Cordova, not mobile development\nExpressions or phrases in languages other than English (I hate it when authors include expressions from Latin or French)\nObscure references to pop- culture topics (although there is an overt reference to Douglas Adams' Hitchhiker's Guide to the Galaxy and one obscure reference to Monty Python)\nPictures of my children or my pets\n\nThis book is not a book for experienced Cordova 4 developers – if you consider yourself an experienced Cordova 4 developer, then you probably should not buy this book.\nHerein I tried to provide complete coverage of Apache Cordova 4; covering enough detail that readers will leave with a complete understanding of what Cordova is, what it does, how it works and how to use it for their mobile application projects. There's a whole lot more to Cordova, many advance topics and more detailed coverage of the Cordova APIs which is covered in the Cordova documentation or in blogs.\nThis book started many years ago as a book called PhoneGap Essentials the book was all about PhoneGap 2.0 and was published right about the time the project name changed to Apache Cordova. The book weighed in at about 300 pages long. The book's first 150 pages covered the available tools and everything a developer needed to know to configure a development environment then create, write, build and test PhoneGap applications. The second half of the book provided a detailed deep dive into each of the (at the time) PhoneGap APIs. The cool part of this second half was that it included, for each API, at least one complete, functional sample application that demonstrated each aspect of the API. The framework's documentation was pretty useful in demonstrating how the API worked overall, but PhoneGap Essentials provided much more thorough examples.\nThe book went on to become the bestselling book on the topic and it was used in university courses around the world. According to Amazon.com, people are still purchasing this book today.\nWith the release of Apache Cordova 3, I reworked the manuscript and published Apache Cordova 3 Programming . This book also weighed in at 300 pages, but was essentially a rewrite of just the first half of PhoneGap Essentials with only cursory coverage of the Cordova APIs provided. This allowed me to go into much more details on the tools and development process.\nUnfortunately, the book was only available as an ebook, so most readers didn't even know it existed. This was exacerbated by Amazon's refusal to link a printed book to an updated version in a different format; I could point people interested in the ebook version of PhoneGap Essentials to the ebook version of Apache Cordova 3 Programming, but I could not do the same for the printed version. The side effect of this was that people continued to buy PhoneGap Essentials even though it covered an older version of the framework.\nIn order to accommodate those readers who were more interested in the Cordova APIs, I reworked the second half of PhoneGap Essentials into another 300 pages called Apache Cordova API Cookbook. In this book, the complete example applications from PhoneGap Essentials were enhanced and expanded and all of the book's content updated for the newer version of Cordova. I'd not covered some topics as well as I would have liked in the first book, so this update allowed me to really expand the coverage of some topics and include even more complete sample applications (32 I think it was).\nBetween Apache Cordova 3 Programming and Apache Cordova API Cookbook, I had written more than 600 pages of coverage of Apache Cordova 3. That's more than twice the size of the original book and a lot of good information for developers.\nWith this book, I've updated Apache Cordova 3 Programming for Apache Cordova 4 plus included new content on a bunch of topics. In my previous books, I",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Email Input on the Web",
  "date":"Mon Apr 27 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430179200,
  "url":"/posts/2015/email-input-on-the-web/",
  "content":"If you access web applications from a smartphone, you may be asked to provide an email address by the application. This will happen during a registration process, but email is also used as a user's user name, so you may find that you have to type an email in every time you log into a site.\nOne of the things that HTML5 gives mobile developers is a special input type for email addresses that simplifies email input for users. Unfortunately, most web developers haven't implemented this cool feature yet, and the result for end users is that every one of us has to work harder to input our email address in these applications.\nTo highlight how this works, I created a sample application that demonstrates the hard way then the easy way to accept email address input in a web application. You'll see screen shots of the application in operation later in the article. You can find the sample application on my GitHub account at https://github.com/johnwargo/email_input.\nIt seems that most web applications today use the default HTML text input field to capture email addresses:\n\nWhen the user places the cursor into this field on a mobile device, he or she will see something like what is shown in Figure 1. The user can type anything they want into the input field using the default input keyboard provided by the mobile device.\n\nFigure 1\nAs you can see from the figure, even though I'm trying to type in an email address, the browser doesn't know that and the @ symbol used in all email addresses is not readily accessible on the virtual keyboard displayed to the user. It's not too painful to press the ?123 key shown in the figure and select the @ symbol from the secondary keyboard, but it's extra work – extra work that every user who accesses the form will have to do every time they use the form.\nWith HTML5, there's a special email input field you can invoke using:\n\nWith this input type, the mobile browser automatically displays an email address-friendly keyboard as shown in Figure 2.\n\nFigure 2\nWith this keyboard, the @ symbol is readily available and the user doesn't need to press any modifier keys to access it. Every single user who uses the form with this input tag has to use one less keypress to enter the email address.\nThis isn't an earth shattering reduction in keystrokes, but at least with this approach an attempt is made to simplify things for users. Developers should always look for ways to simplify things for their users and this is a great example.\nIt's not a lot of work to implement this, simply change the input type from text to email. Now, many of you may be asking yourself what the impact is for browsers that don't support the HTML5 input tags. Well, HTML5 as a draft has been around long enough that you'll be hard pressed to find a modern smartphone that doesn't support them. However, for those browsers, if the email type isn't supported, the browser will simply ignore the tag and render the default input field.\nSo, there's no impact on users if the tag isn't supported by the browser, but direct benefit to smartphone users if it is. There's no reason not to update all of your email input fields to use this input tag right away.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Stupid Web Forms",
  "date":"Sun Apr 26 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430092800,
  "url":"/posts/2015/stupid-web-forms/",
  "content":"I'm constantly reminded of how web application designers don't pay attention to the impact their decisions have on their application users. I've written here before about this, but I think it's time to bring it up again.\nWhen designing a form or dialog, it's important to remember that if you're asking users to make a selection when they first access the site, you should make sure to store that selection so that you don't ask them to make the selection every time. If it's something simple, something the user only needs to address once, most web designers allow the user to make the necessary choice, store the resulting decision and move on. The user's not asked again, so it really doesn't matter how challenging the initial form is if the user is only going to ever use it once.\nOn the other hand, some sites require that the user make a decision or selection every time they access a site or an area in a site. I don't have a problem with that, sometimes it's necessary and the user just has to deal with it. An example of this is shown in Figure 1.\n\nEmployees that migrated to PayFlex sometime in the past will need to be able to access their pre-PayFlex data as well as their PayFlex data. Makes sense to ask the user which way he or she wants to go, right?\nIn this case, PayFlex has implemented this incorrectly. Whenever you login to the site and try to access this area of the site, you have to make this selection. The problem is that after a while, you'll never need to go back to the old system as all of your current activity is being performed with the PayFlex stuff. OK.\nThe problem I have with this is that the developer who implemented this part of the application didn't make any effort to keep the user's previous selection. It's OK to ask me every time as there's no way for the site to know whether I want to access the old system or the new system. But, once I go down a particular path, it's likely that the next time I access the site I'll want to go the same way again. What they should have done is store the user's decision then preselect that option the next time the user comes into that portion of the site.\nIf going to the same place, all the user has to do is click the continue button (the previous choice will already be selected) and they're golden. If not going to the same place, then all the user has to do is select the other option and click continue to go down that path. By making this simple change, I eliminate, can potentially eliminate 50% of the selections the user has to make on this form. It's either one click or two clicks, but most of the time it will be only one click.\nBy not implementing this simple fix, this company is making every single user make a selection before clicking submit – EVERY TIME THEY ACCESS THE SITE. This is completely unnecessary and wastes your user's time. You should always be on a lookout for ways to eliminate unnecessary actions by your users.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Migration Completed",
  "date":"Sun Apr 26 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430092800,
  "url":"/posts/2015/migration-completed/",
  "content":"Back in December, I set about migrating this site to a new hosting provider. Hackers had been having some fun with my site and I was having trouble blocking their efforts. Online advice said to whack the site and start over, so that's what I tried to do.\nI setup a new hosting account then backed up my existing site. Next I tried to restore the existing CMS data into a new CMS installation (of the same CMS software, of course). The plan was to eliminate any old or nefarious application files and basically start from scratch by doing a new CMS installation with old data. Once everything was working, I planned on upgrading everything to the latest version of the CMS software.\nI didn't spend a lot of time on this (over the last 5 months), but I did take a few vacation days to work on this. The result was that I failed miserably, I simply wasn't able to restore my CMS files into a new CMS installation. The biggest issue I faced is that when I brought up the new site, it 'worked' but when I tried to add my plugins back to the CMS, the legacy installations were still there and it became quite a mess.\nI tried to manually whack the old plugin installation data (the new CMS didn't actually have the plugins anymore, but the database entries were still there) but that didn't work. The CMS wasn't capable of supporting what I was trying to do.\nSigh.\nSo, anyway, what I did was backup the site then restored it into the new hosting account. Everything worked (yippee). Next, I upgraded the CMS and almost everything worked. I poked around a bit and fixed the most glaring issues (for me) and completed the migration this evening.\nThe contact form isn't working right now – I had CAPTCHA problems with it on the old hosting account and now I just need to remember what I did to fix it. I'll work on it this week and will hopefully have things back up and running again. If you need to contact me, my email address is my first name and this site's domain.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Leaving SAP",
  "date":"Sun Apr 26 2015 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1430092800,
  "url":"/posts/2015/leaving-sap/",
  "content":"For those of you that follow me on Twitter or are connected with me on LinkedIn, you probably already know that I no longer work at SAP. This wasn't my idea, instead it was part of an office consolidation that SAP has undertaken. Since I worked in the development organization but wasn't working in an office with my team, my position was eliminated. I live in North Carolina but the people I worked with were in Dublin, CA and Walldorf, Germany so hence the source of the problem.\nFortunately for me, SAP made it pretty easy for me. They gave me some time to see if I could find another position with SAP (I didn't). Plus they did some other stuff (which I can't talk about) to help me in my transition. Overall, a stressful but not a very painful process. Bonus!\nI really liked working at SAP. They treated me very well and I was very happy that I was able to work on software development tools (something that interested me greatly). I really enjoyed working with all of the smart people at SAP. As the Product Manager for what was essentially SAP's hybrid development SDK, I was in the unique position where my day job aligned with my hobby. As a writer about and contributor to the Apache Cordova project, owning some of the Cordova-based products from SAP was the perfect place for me.\nWhen I joined SAP, I'd pretty much decided that I was going to stay there until I retired. It was a great job with a great company and I thought I could stay for the duration of my career. Unfortunately, being remote became a problem and I was unwilling to move to California (although I would have been interested in moving to Germany). Over the years, some opportunities presented themselves to me, but, because I wanted to stay at SAP, I didn't really consider them. Now that SAP forced the separation, it gave me some time to pursue some really good opportunities.\nDuring this process, I confirmed that only a small percentage of people find jobs on Job Boards; most nowadays find jobs through their existing connections. Once I decided that I wasn't going to find a new position within SAP, I posted on LinkedIn that my position had been eliminated. It wasn't long before my inbox was filled with emails from my existing contact base offering to help me. I quickly updated my resume then responded to everyone. Before long, I'd been introduced to opportunities in about 10 companies and I began actively interviewing with many of them. Of course, nothing came of some of them, but I was able to begin actively working with 6 different companies on 11 different opportunities.\nI only had a certain amount of time to find a job, so I set a deadline for myself and got to work. I was able to secure 2 job offers a few days past my deadline and had one more lined up, but not formally offered. Essentially, I had three opportunities to choose from. Unfortunately for me, I was really, really interested in all three of them. Sigh. I was hoping I'd have a choice to make (and I succeeded), but I wasn't expecting that I'd be solidly interested in all three of them. Sigh, the pressure increases.\nFor many years, I led custom development (consulting) and product development teams for different organizations. I really enjoyed leading teams. When I got into mobile, I obtained individual contributor roles and had those for the last 10 years or so. With this job…transition, I pursued some individual contributor roles, but also one where I'd be able to build and (someday) lead a team of technical people. At the end of the day, I had to choose between the three opportunities and I did.\nI start my new job on Monday – and will tell you all about it once I start. Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Migration Update",
  "date":"Sun Feb 01 2015 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1422835200,
  "url":"/posts/2015/migration-update/",
  "content":"As you can see, it's been a while since I posted to this site. Well...I started the migration to a new hosting provider on December 1st and spent a couple of days on it before taking a break for the holidays. I had a couple of lingering problems, so I spent the day today trying to get around them.\nI pretty much did, but not other problems have arisen. Sigh - this has been really hard as it's next to impossible to migrate a Joomla! site the way I'm forced to do it here.  I'd tell you that I'll write about my experiences doing this, but then I'd be telling lies.\nAnyway, I'll keep hammering away at this and let you know when it's done. I have a stack of articles I want to write and post and can't wait to get back at that.\nIn the mean time, Apache Cordova 4 Programming is 'finished.' I've completed the manuscript and it's been through the editing process, now I'm waiting to see proofs before it goes off to the printer.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Site Migration Starts Today",
  "date":"Sun Nov 30 2014 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1417392000,
  "url":"/posts/2014/site-migration-starts-today/",
  "content":"I will be migrating this site to a new hosting account starting today. I don't know how long this process is going to take, so please be patient as I work through this.\nI'm migrating the site for several reasons. It's been running on one of my personal hosting accounts and I want to move it to its own account/server for performance and security reasons. It's been running on Joomla 2.5 for a while and I want to get it to Joomla 3.x. Hackers have been having some fun with my site lately, so it's probably a good idea to clean everything up and start all over.\nI'll let you know when it's done - for you, you shouldn't notice any difference (If I do this right). Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Where to Find Me @ SAP TechEd && d-code Las Vegas 2014",
  "date":"Mon Oct 13 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1413244800,
  "url":"/posts/2014/where-to-find-me-sap-teched-las-vegas-2014/",
  "content":"Next week I'll be attending SAP's TechEd conference in Las Vegas. In previous years, I've attended the conference and spent most of my time visiting with customers on the show floor. This year I've been assigned several sessions (along with some colleagues), so I thought I'd let you know what I have going on this year.\nFirst I'm doing a session entitled “MOB101: Hybrid Mobile Application Development with Kapsel” – it's a one hour lecture session where I introduce Hybrid development with the SAP Mobile Platform. I'll talk about what Kapsel is, what it does, how it works then show you how to build a Kapsel application start to finish. For Las Vegas, the session is offered twice:\n\nTuesday, October 21, 2014 from 2:00 PM to 3:00 PM\nWednesday, October 22, 2014 from 3:15 PM to 4:15 PM\n\nNext I'm helping Jeff Gebo deliver a two hour hands on session on hybrid development entitled “Mob160: Build an HTML5 Hybrid App with Kapsel” This session starts with a short introduction to the SMP Hybrid SDK (Kapsel) then jumps into the coding. First you'll setup a SMP application definition for the session project then build a hybrid application that connects to SMP and utilizes the Kapsel Logon and OData plugins to onboard to the SMP server then consume an OData source while offline.  For Las Vegas, the session is offered twice:\n\nTuesday, October 21, 2014 from 4:30 PM to 6:30 PM\nThursday, October 23, 2014 from 8:00 AM to 10:00 AM\n\nI'll be joining colleague Senthil Krishnapillai in a session entitled “Increase Mobile App Adoption with Security that Enhances Usability” being held Tuesday, October 21 from 12:15 PM to 01:15 PM.\nI'll also be available for a networking session entitled “Hybrid Development with SAP Mobile Platform” which will be held Wednesday, October 22, 2014 from 1:30 PM to 2:00 PM. The purpose of the session is to block off 30 minutes for attendees to meet with you to discuss topics related to the session title. In this case, I'll be available to discuss questions around Hybrid development using SMP.\nI have a second networking session with Senthil Krishnapillai entitled “Use the SAP Fiori User Experience for Improved Connectivity and Security” scheduled for Thursday, October 23, 2014 from 3:30 PM to 4:00 PM. In this session, we'll cover how to enhance the security of SAP Fiori on mobile devices.\nThe remainder of my time, however much that will be, will be spent at the Fiori Café talking about Fiori Mobile. Come by the Café to learn more about SAP Fiori, a lot of subject matter experts will be on hand to answer your questions.\nI will have a few copies of my latest book on hand, so I'll likely raffle them off in my sessions.  Who knows, perhaps you can leave with a copy.\nI'll also be at TechEd &amp;&amp; d-code in Berlin; I'll update you on that one after this TechEd closes.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Poorly Designed Web Sites",
  "date":"Mon Sep 15 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1410825600,
  "url":"/posts/2014/poorly-designed-web-sites/",
  "content":"As look at the world around me, I'm surprised that in the world of the connected, mobile user, that companies are still not thinking of mobile-first users. There are millions or billions of mobile devices sold every year, but companies with public facing web sites still don't seem to notice, and I'm really surprised by that.\nThe local Charlotte BIG insurance company is Novant Health, and they're usually pretty organized. I was in one of their facilities a while back and noticed that there was free Wi-Fi, so I decided to connect. After selecting the SSID and connecting to the network, I was presented with the confirmation page shown in Figure 1.\n\nSo, what's happening here is that Novant Health recognized that they had a lot of mobile users within their facility and made a conscious decision to provide them with a little extra service (free Wi-Fi) but made no effort to make the confirmation page friendly to mobile devices. Sigh.\nIf you look at the page, their logo is pretty prominent, but below the fold as it were, so it's not in the way too much. They probably should have used a smaller logo and put it at the top of the page where it is on every other web site they have.\nThe terms of use section is completely unusable. What's interesting about this is that someone had to go out of their way to format the text so that it would be unreadable on a mobile device. Taking the text and wrapping it with paragraph tags would have allowed the content to fill the available page space and made it easily readable, but the developer who did this tried to put it into a fancy, and I think scrollable, window and therefore made it essentially unreadable by a mobile user. Do you see scroll bars or anything that would indicate to me that I can scroll through the text to read all of it before clicking the 'Accept' button?\nThat takes me to the Accept button – can you even see it? It's so small, that you might not even know it's there. You have to look really, really close to see that there is an 'I agree with the Policy Above' button below the useless text windows. A button that small would be almost impossible to tap with a finger on a smartphone. Apparently I'm supposed to read the terms of use (I really can't in this window) and click the button I can hardly see in order to be able to use the Novant Health Wi-Fi network.\nLike I said, an almost unusable page.\nWhat's interesting is that it's not that hard to make mobile friendly web pages out of something as simple as this small page. There are hundreds, literally hundreds, of HTML frameworks that could be used to automatically adjust the format of this page to accommodate any size browser and any type of device.\nTaking the same page content, rendering it as a simple page with no fancy extra windows, just a logo, heading, content and a single button – would take no effort whatsoever. Just do the tiniest bit of research into HTML5 frameworks, pick one then mark up your text (using proprietary tags for some frameworks and simple CSS tags for others) and you're all done. An extra 5 to 10 minutes of work and suddenly your web page works on any device.\nFor my books, I've recently been doing a lot of work with Adobe Topcoat and, as a CSS-only solution, it's pretty easy to add the classes to your markup to make a mobile Beautiful page in no time. The same could be said for many other frameworks as well.\nWhat I can't understand is why these companies aren't making the effort to do this. It's Wi-Fi, they're giving external users access to a wireless network. They have to know that the majority of users making use of this capability will be doing so from a smartphone or a tablet. There will be some laptops, but in general the majority of visitors won't be bringing laptops with them.\nI'm assuming they have some sort of tracking capability; that they can tell what systems are using their network – a little bit of checking would allow them to see what their audience looks like.\nWhat's interesting about this example is that it seems that they didn't think to test the site on mobile devices, otherwise they would have seen how useless this page was. In my case, I was using a Samsung Galaxy S4 device – probably one of the most popular families of Android devices.\nDevelopers – Know your audience and code accordingly. There is no need for fancy, small, scrollable windows on a smartphone device. Just wrap ALL of your page's content in  tags and let the browser render it exactly as it sees best for the device real estate.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Stupid Developer Tricks"
  
  ]
  },

  {
  "title": "Bootstrap Complete NavBar Example Application",
  "date":"Sun Aug 31 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1409529600,
  "url":"/posts/2014/bootstrap-complete-navbar-example-application/",
  "content":"I had an idea a while back for a web application I wanted to create. I'd not worked much with Bootstrap (https://getbootstrap.com/ and wanted to have some experience with it, so I thought I'd play around with building the app I wanted using the framework.\nThe Bootstrap web site is pretty detailed, and I quickly found an application template I could use for my application. As I poked around, I noticed that the template allowed me to add a simple menu to my application and that worked for me. As I played around with it, I found that every single example I could find ANYWHERE for how to use the Bootstrap navbar (the menu) only showed how to create the menu, not anything about how to structure a the page sections within the application that would appear as you selected each menu item. I checked all of the Bootstrap web site, stack overflow and any other site I could find with examples, but there were none that showed a complete example of a complete Bootstrap web application that had a menu.\nYet another example of a software project where the documentation for things you don't already know how to do assume that you already know how to do it. Sigh.\nAnyway, I found a post on Stack Overflow that showed the JavaScript code needed to process the menu and customized it to suit my needs. The example I found at https://stackoverflow.com/questions/19579083/bootstrap-how-to-use-navbar showed how to deal with a simple menu, but what I implemented, based on the template I was using, had two menus. I also found another Stack Overflow post that described how to set the active menu item in a Bootstrap application at https://stackoverflow.com/questions/11813498/make-twitter-bootstrap-navbar-link-active. With these two posts, I was able to cobble together what I needed.\nLet me show you what I created:\n\nAs you can see from the image, the navbar has two menus, one on the left (menu 1, menu 2 and menu 3) and one on the right (with settings and an about page). So my JavaScript code has to deal with setting the active menu, no matter which navbar item was selected.\nAnyway, I've posted the example code to GitHub at https://github.com/johnwargo/bootstrap-navbar-complete. The web application starts with the following code:\n\nIt defines the two navbars and mimics most of the examples found on Stack Overflow and the Bootstrap web site.\nNext you create individual pages. First of all, you define a container using the following div:\n\nThen, within the container, define separate divs for each 'page' of content:\n\nNext you need some JavaScript code that defines an event listener for the menu.\n\nThe event listener first deselects the currently selected menu item then sets the current selected menu item to active. Next, in the container portion of the page, all of the divs in the container are hidden then the selected one is unhidden.\nThat's it,\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "JavaScript",
  
    "Web Development"
  
  ]
  },

  {
  "title": "When to Check for Updates",
  "date":"Sun Aug 10 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1407715200,
  "url":"/posts/2014/when-to-check-for-updates/",
  "content":"I've been trying to build a sample application using the Ionic Framework, an HTML5 framework specifically designed for hybrid applications. I read the instructions, downloaded the code and initiated the command to create a new project.\nWhat happened? Failure.\nI posted my issue on their forum only to be told that my Cordova development environment must be old. I explained that it was all up to date and working perfectly for every other Cordova development I've ever done and what I got for my trouble was a link to a video that showed me how to install Ionic on Windows.\nSigh. Didn't I just explain that I have a fully functioning Cordova development environment? Sigh again.\nAnyway, I started looking around for a potential culprit. My Android dev tools were all up to date and so was my Cordova installation. I noticed that NodeJS was a little old, so I just installed the latest and greatest version of node.\nWhen I tried the command again, I got the following…\n\nI have the Ionic tools installed and the command runs. It downloads some stuff, then downloads some more stuff then sets about creating a project and adding some plugins to it. As you can see, it's able to install two Cordova plugins (device and console), but where it fails is when it's trying to install a proprietary Ionic plugin.\nIt tells me that there's the potential that my Cordova is too old, but it's already been able to install two Cordova plugins without any problems. What could it be about that Ionic plugin that suddenly breaks the Cordova CLI?\nOK, so we know that my Cordova is up to date and we know that I can add plugins. I'm pretty sure this isn't a problem with my Cordova implementation – I've created Cordova 30 apps or more with this configuration (and written three Cordova books using this config). So what's the problem?\nWell, the next thing the Ionic CLI tells me is that my Ionic CLI is out of date and that's what prompted me to write this blog post.\nAs a developer, when should you check to see that your stuff needs updating? Do you do it before you perform any tasks or do you perform a bunch of tasks, fail, then check to see if there's a new version of the tool(s)? That was a trick question because the answer to that question is ALWAYS the first choice – check for application updates BEFORE your tools do anything.\nThat's the only option that makes sense.\nWhy would you tell me I'm running an older version of a tool only AFTER I've tried to use it and failed? Whoever wrote that particular piece of code simply wasn't paying attention.\nOK, so I updated the Ionic CLI and ran the command again, only to receive the same error – apparently the Ionic CLI can install Cordova plugins, but not their own as shown below.\n\nI'd ask for help again, but I've already done that and all I hear back is that I should check to make sure my development environment is up to date. Nobody seems to want to try to understand what's happening here or suggest actual steps I can take to try to fix this.\nIt looks like my next book isn't going to have a section in it about how to use Ionic with Cordova. Too bad.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "CEF & Monty Python",
  "date":"Sun Aug 03 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1407110400,
  "url":"/posts/2014/cef-monty-python/",
  "content":"Note: The original title for this post was supposed to be 'How is the Chromium Embedded Framework Documentation like a Sketch from Monty Python's Meaning of Life?' but the title was just too long.\nI was getting some exercise yesterday and came up with an idea for an app I wanted to write. The app needed to work for Windows as well as Macintosh, so I started thinking about how I'd do it. I'm a big Delphi developer, and the recent Delphi tools support Windows &amp; Macintosh, but I imagine other folks would be interested in this thing, so doing it in something that required a commercial software license to maintain didn't make sense.\nNext I started thinking about whether I could do it as a Cordova application. Windows is a supported platform for Cordova, so that would work, but Macintosh support is only available pre-3.x. I could probably dig up some work in progress OS X support somewhere, but if it's not part of the core, it didn't make sense for me.\nThen I started thinking about Adobe Brackets. This code editor worked on Windows, OS X and Linux, so they'd clearly picked an approach that worked on each. It's written using web technologies, so that would work for the app I wanted to build.\nI started digging into the Brackets code to see how they'd done it. A while back, a colleague convinced me that Brackets was written in PhoneGap, but in reading around on the blogs it quickly became clear that it was created using the Chromium Embedded Framework (https://code.google.com/p/chromiumembedded/).\n\nSo, I started digging around in the CEF documentation and found a bunch of information. There was an introduction page at https://code.google.com/p/chromiumembedded/, a tutorial at https://code.google.com/p/chromiumembedded/wiki/Tutorial and some general usage stuff at https://code.google.com/p/chromiumembedded/wiki/GeneralUsage\nNice! I love it when an open source project has actual guides (that's one of the things I love about Apache Cordova).\nI quickly read through all of that material and quickly discovered that after reading all of it, I still didn't understand how it 'worked.' The materials talked about where to download the stuff and how to build it, but nothing about how to 'use' it. The tutorial and usage guides talked about threads, callbacks, plugins and all sorts of stuff, but nothing about how to actually 'use' it. It's clear that after I downloaded all of these files, I had something I could run and use, but how did I actually make it do what I wanted it to do?\nSigh.\nI scanned through the stuff again and still didn't see it. I saw all sorts of source code and highly technical stuff, but not what I needed to know to make an application that did what I wanted to do.\nEven the Brackets source didn't help me as it's just the source code for the app and there was some external process for building it into the actual platform-specific executables. Sigh again.\nFinally, I started searching around again to find some post or article somewhere that told me what I needed to do to make this thing my own. I finally stumbled on an article from Intel at https://software.intel.com/en-us/html5/blogs/an-html5-project-with-chromium-embedded-framework Here they told me exactly what I needed to do to make the CEF my own – open a configuration file and edit a particular variable to point it to the web application content you want to load.\n\nAh ha! That's what I needed to know. All that other stuff about threads, plugins, callbacks and so on is interesting, and that's information I'll eventually need, but for now I simply need to understand how to get started. All those pages of content and somebody simply forgot to add the important part – how to specify what content is loaded into the browser container.\nSo, apparently, for each target platform, you have to specify the content you want loaded in the browser, then use the build process to package it all together into the executable you need. Tada!\nThe issue for me is that developers working on open source projects are so excited about the technical stuff that they skip the getting started stuff and jump to the 'important' stuff. So much of the 'documentation' out there is written, in my eyes, from the standpoint that you already know how to do this stuff. I'm not kidding, most every time I take a look at one of these projects, I struggle to get past all the unimportant stuff in order to be able to find the simple, everyday, what do I do with this thing.\nThat's why I write my articles and books the way I do – I assume NOTHING and expect that if you're brand new to a topic, what I'm providing will give you everything you need. If you're already familiar with the topic, I expect that you'll be able to scan the content in order to find interesting tidbits. If you read the reviews of my more recent books on Amazon, you'll see that people seem to agree.\nDevelopers, please listen to me. When you're documenting your stuff, assume nothing. Let me decide what's important and what's importan",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Free Introduction to Apache Cordova",
  "date":"Wed Jul 30 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1406764800,
  "url":"/posts/2014/free-introduction-to-apache-cordova/",
  "content":"Whenever I publish a book with my publisher, they always pick one chapter and post it online for anyone to read. Picking the right chapter has always been a challenge for me because I want them to publish a chapter that's interesting enough to make you want to buy the book while at the same time not being so good that you get everything you need and don't buy the book.\n\nGet it? Please buy my books. I write them because I like to write and think I have a special skill when it comes to describing technical topics, but at the end of the day I like the extra income. Buy my books, please?\nAnyway, today, my publisher, Addison-Wesley/Pearson Education, published a chapter from my latest book. The book is called Apache Cordova API Cookbook, and they selected Chapter 1: An Introduction to Apache Cordova (https://informit.com/articles/article.aspx?p=2235541).\nThe publisher usually consults with me on which chapter to publish – they typically ask me which one or ones I would suggest then go off and pick one then put it online. This time they simply picked one and went with it, so I didn't have any say in what happened here.\nAs the book is all about the Cordova APIs, so they could either have picked one of the API chapters or picked the only generic chapter: chapter 1. The chapter introduces you to the concept of Apache Cordova, what it does, how it works and what it's used for.  The book is targeted to mobile developers who have at least a little exposure to Apache Cordova, so this chapter is for those people who skipped the requirements and bought the book anyway – I had to give them a quick intro so they'd be able to understand the remainder of the book. It's a good chapter and should give you a good teaser of what kind of stuff you'll find in the rest of the book. If you like it, please buy the book. If you're just getting started with Apache Cordova or Adobe PhoneGap development, you may want to take a look at the companion book: Apache Cordova 3 Programming (corodvaprogramming.com).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Apache Cordova API Cookbook Print Copies",
  "date":"Sat Jul 12 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1405209600,
  "url":"/posts/2014/apache-cordova-api-cookbook-print-copies/",
  "content":"![Apache Cordova API Cookbook](/images/2014/acac-print-copies cropped-150.png)\nPrint copies of Apache Cordova API Cookbook arrived on Friday; my expectation is that they will be available for shipment from Amazon.com and other retailers by the end of next week.\nThis book, along with my Apache Cordova 3 Programming, provide 600 pages of coverage for Apache Cordova. These two books give mobile developers everything they need to be able to write cross-platform mobile applications using Apache Cordova or Adobe PhoneGap.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PhoneGap Essentials Sales",
  "date":"Wed Jul 02 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1404345600,
  "url":"/posts/2014/phonegap-essentials-sales/",
  "content":"\nI keep hearing from readers who have just started reading my PhoneGap Essentials book. That book was published more than two years ago and PhoneGap has changed dramatically since then. The code in the book should still work - not much has changed on the API side of things. The content covered in the first half of the book however is no longer valid.\nI rewrote the first half of PhoneGap Essentials last year and released it as Apache Cordova 3 Programming in December. That book takes the first 150 pages dedicated to PhoneGap development and PhoneGap tools and updates it for Cordova 3 plus expands it out to about 250 pages. There's an additional 50 pages on the APIs that covers them at a high level, but if you have the Essentials book you have the same information (just a little older).  You can read more about the book at https://cordovaprogramming.com.\nThe second half of PhoneGap Essentials was all about the Cordova APIs, about 150 pages worth. I just finished rewriting that content (and expanding it to about 300 pages) and published it as Apache Cordova API Cookbook - the book will be in stores in about a week. You can read more about the book at https://cordovacookbook.com.\nWith these two books, you've got 600 pages of coverage for Cordova 3.\nI think what's happening, please correct me if I'm wrong, is that while the people I work with use Cordova, much of the world only knows of it as PhoneGap. I'm wondering whether not having PhoneGap in the title of my latest books is somehow hurting sales. As PhoneGap is a distribution of Cordova, you'd think that a book on Cordova would address both markets. If I change future book titles to have PhoneGap instead of Cordova in them, I may lose out on an audience that's interested in Cordova and not PhoneGap. Sigh.\nI tried to post a comment on the Amazon listing for PhoneGap Essentials letting folks know there was an updated version of the book available. Amazon refused to publish it.\nI'm getting ready to start work on Apache Cordova 4 Programming, with a planned release of very late this year (December at the earliest) but probably early next year. I'm planning on expanding this book considerably and hope to get about 400 pages of content in there. When I get done, between the two books, I'll have published more than 700 pages of content on Apache Cordova.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Comment Spam",
  "date":"Sun Jun 29 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1404086400,
  "url":"/posts/2014/comment-spam/",
  "content":"I mentioned this on twitter a while back, but I'm consistently amazed by how much effort is made by hackers to hack into my personal web sites. I'd be really interested in seeing what percentage of internet traffic is taken up by these types of efforts (not on my sites, but on content management systems overall). I plan on doing some analysis of this, but simply haven't gotten around to it.\nAnyway, I had some issues with the CAPTCHA on this site, and my comments plugin provider isn't responding to any forum posts on the topic so I had to just leave the comments on and use the plugin's moderation capabilities to weed out the spam. What's interesting about this is that I generally only get spam on just one of my posts as shown in the figure below.\n\nI don't know what it is about that particular topic that attracts the spammers, but it sure does (to the tune of about 50 spam comments a week).\nApparently there's some known bug in GeSHI and/or Joomla and the botnets are trained to look for it to see if they can capitalize on it. All the spam comes from the same botnet I think because the format of the message is always the same, just the topic and target change. In the old days, the comments would be entered by a human, or at least written by a human, so the messages had a real subject and real content. I'm really not sure why anyone things that comments with random characters in the subject and body of the comment wouldn't raise red flags and get the comment deleted, but that's what's happening time and time again.\nWhat I'll probably do is switch out the comment plugin for another that actually works with Joomla's built in CAPTCHA (see, CAPTCHA is an acronym so I'll spell it that way, spam isn't, so you won't see me capitalizing spam that way). This is the second comments plugin I've used, and I hate to whack all the existing comments again, but I don't get that many comments (only spam) so it probably isn't a big deal.\nPeople are reading these articles, right?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "First Arduino Project",
  "date":"Sat Mar 15 2014 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1394928000,
  "url":"/posts/2014/first-arduino-project/",
  "content":"My dad was a tool geek, I'm a gadget geek. All my life I've been drawn toward technology. When I was a kid, I was constantly biking to Radio Shack to pick up one of their assemble-it-yourself electronics kits. I build radios, sound generators and anything I could get my hands on. I wanted to be an Electrical Engineer, but my grades weren't good enough, so I went into Physics and Computers – go figure.\nAnyway, my son's a gadget geek as well. He's 10, so all he knows is smartphones and tablets – every time I get a new device, he goes crazy for it and tries to show me how it works. Doesn't he understand that I'm in the smartphone business and will always know more than him for at least a few more years?\nAnyway, I've been playing around a bit with the Raspberry Pi (I've posted several articles here about my experiences) and I've always wanted to play with some programmable microcontrollers. My neighbor got me to take a look at some microcontrollers from Texas Instruments, but I've not done anything with them yet. I'm most interested in the Arduino, but again haven't had time to play much with it...until now.\nMy son and I were discussing possible geek projects to work on and we decided to trick out a…well, it's a secret, but I'll write about it as soon as I can. We decided we needed a very small package for this project and I knew the Arduino was going to be too big. So I started looking around at smaller versions of the Arduino to use. The first one I found was the Teensy (https://pjrc.com/teensy/), its super small, and I think this is the one we'll ultimately use for our 'project.'\nI wanted to breadboard this out first, so I picked up an Arduino Micro (https://arduino.cc/en/Main/arduinoBoardMicro) from Adafruit (https://adafruit.com/products/1086) – very nice, very small (although bigger than the super small Teensy). This one comes with headers (the Teensy doesn't) and fits nicely into a breadboard as you can see from the following figure.\n\nFor this particular project, the Arduino needs to know how it's oriented in space, so I picked up a Arduino Accelerometer module from Adafruit (https://adafruit.com/products/163). The 3g one seemed good enough, but since I bought that one the Adafruit team came up with a 16g so I picked up one of those as well. I imagine the 16g model will make it into our 'project.'\nI planned on working on our project this weekend, but of course forgot to pick up a breadboard. My son and I headed off to Radio Shack (oh, the memories from when I was a kid), picked up a breadboard, battery holder and a battery and got to work.\nI first installed the Arduino IDE then connected the board to the computer and tested it worked by running the blink sample application. Next I wired up a single LED and got that working. After that, I wired in 5 LEDs, showing my son how to use the breadboard and make the circuit. With 5 LEDs working, I started playing around with the application code to see if we could come up with some cool blink patterns. I did them the hard way, turning each light on and off as needed individually, so I could show my son how the code worked. He quickly got bored, so when he went off to play with his friends, I refactored the code, added arrays and loops and created some pretty tight code. Tomorrow I'm adding a Cylon pattern, it will be fun.\nNext I added the headers to the accelerometer module; I wish it came with headers pre-installed because I quickly mucked up that task. Anyway, with the accelerometer wired in, the project can tell its orientation in space. Tomorrow my son and I will start programming different behavior depending on the project's orientation in space. Like I said, I'll write all about it once I get it all done.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "Password Pain Redux",
  "date":"Mon Feb 10 2014 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1392076800,
  "url":"/posts/2014/password-pain-redux/",
  "content":"In my previous post, I wrote about one of my biggest software pet peeves – registration forms that have specific password requirements that are not communicated to the user until AFTER a password has been entered. This morning I found one that was even worse than the Google Coder one I showed earlier.\nI was playing around with the Intel XDK development tools for web applications. After I got it installed, it prompted me to create an account. I filled in all of the fields and went looking for any indicator that the form had password requirements. None found, so I clicked the Submit button only to find out that for some unknown reason, Intel requires a special character in the password as shown at the very bottom, in small print, in the following figure:\n\nSo, I dutifully added a special character (I'm not telling you which one) and clicked Submit again only to find out that they had yet another requirement. Apparently you also have to have a number in your password, but Intel made no effort to inform me of any of this.\nAt this point, I've failed twice and I still don't know if my password with a special character AND a number will actually fulfill the requirements. I crossed my fingers and clicked Submit for the third time only to find out that I had actually, unbeknownst to me, complied with the password requirements. Woohoo!\nDevelopers, when you have an input form that has specific input requirements – TELL ME WHAT THEY ARE. I shouldn't have to guess what your password requirements are; you know what they are, so tell me BEFORE I start typing in my password. I know you have limited screen real estate for listing out the requirements, but there's no reason you can't give me a button or a link to click on to view the requirements.\nI'm assuming you like your users and actually want us to use your development tools – so don't make it so hard for us to actually use them.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Password Pain",
  "date":"Mon Feb 03 2014 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1391472000,
  "url":"/posts/2014/password-pain/",
  "content":"I recently learned about a cool web development server for the Raspberry Pi. I want to teach my son about computer programming and this seemed like an interesting way to do it. The server is called Google Coder and it's delivered as a Raspbian image for the Pi. Pretty cool; I'm hoping to learn more about it and write a bit about my findings here.\nAs I set it up and started playing with it, I was hit by one of my pet peeves. First you fire up the server then connect to it via your desktop browser (right, it's not something you use on your Pi, but instead something you host on your Pi and connect to it from your desktop PC). When you connect to the server, you're prompted to provide a password in order to access the system as shown in the following figure.\n\nHonestly I'm really not sure why I need a secure connection to my Pi (notice the HTTPS in the browser's address field) and I'm also not sure why I need a password, but I'll dig into that at some later time.\nAnyway, so it wants me to use a password so I went ahead and typed on in. After clicking the 'Save My Password' button shown in the figure, what I see next is the following:\n\nThere it is – one of my biggest developer pet peeves. If you know that you're going to want me to include upper case, lower case and numbers in my password, why not tell me BEFORE I tell you the password I want to use?\nI see this all the time and it makes absolutely no sense to me. You're asking me for input and you know exactly how you want that input formatted, why don't you share that information with me so I can save a little time here? After all, it's not like you have a hidden camera and you can get some pleasure from watching me type in a password only to later learn it doesn't meet your requirements.\nDevelopers, if you have any input, password or any other requirements you're obligated to tell me what they are BEFORE I provide you with the input. There's no other way. You took the time to type in the requirements into the error message shown in the second figure, why not copy and paste the exact same information into the original input form?\nI know why it was done this way, some designer designed the password form and it had to look cool and clean. The error warning was an afterthought or was implemented by someone AFTER the design of the password form had been completed. Rather than think through the process and your requirements for the system, they left the input form clean and muddied it up later ONLY if the user didn't accidentally type in a password that met the requirements.\nDo your users a favor and think through the whole process before doing the coding. Give the designer all of the requirements so they can be taken into account from the very beginning. That way you'll make happier users.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi",
  
    "Internet of Things (IoT)"
  
  ]
  },

  {
  "title": "BlackBerry 10 Charging Foibles",
  "date":"Mon Feb 03 2014 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1391472000,
  "url":"/posts/2014/blackberry-10-charging-foibles/",
  "content":"If you've been reading around here you should know that I love BlackBerry, but BlackBerry 10 is really starting to annoy me. For all of BlackBerry's focus on quality and design, I'm find BlackBerry 10 to be really, really hard to use on a day to day basis. So many of the things I loved about BlackBerry just aren't in BlackBerry 10 and I'm finding the UX to be…klunky.\nI went out of town this weekend to hang out with some friends. I have a BlackBerry Z30 device, and it has a HUGE battery, so I expected to get a whole day's use out of it, but no go. Around 7 PM, after starting the day with a full charge, the battery was on its last legs.\nFortunately for me, the folks at Adobe gave me a free USB battery at PhoneGap Day 2013, so I pulled it out in order to give myself a boost. I only got a few minutes out of the battery, but that's not what I'm here to talk to you about.\nAs the battery started to lose its charge, the warning shown in the figure below started to appear. Not a big deal, I like being notified that I'm running low on juice. The problem is that I couldn't get the darn thing to go away.\n\nHere's what happened, I was trying to charge the device, but my USB battery was out of juice itself. So, the BlackBerry knew it was connected to a power source of some kind, but since it wasn't getting any juice itself, it threw up that warning. It would display for a while, go away for a few seconds then immediately come back – over and over again. The problem is that it's really hard to use the device with this message constantly popping up and going away. The touch screen is essentially unusable as long as this behavior continues.\nI was trying to meet some friends and my battery dying and this stupid continuous warning was really annoying. I finally figured out that when I unplugged the USB battery, the message would go away and I could again use the device. Ugh.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Airplane Etiquette",
  "date":"Sat Feb 01 2014 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1391299200,
  "url":"/posts/2014/airplane-etiquette/",
  "content":"I spent the weekend in Buffalo snowmobiling with some very old friends. As I flew on several Southwest airlines flights I was reminded of a little piece of airplane etiquette that most people don't think/know of.\nImagine you get on the plane and sit towards the front of the plane, but get on later in the process and the front overhead compartments are full. You move back to an open overhead compartment further and store your stuff then head up to your seat for the ride to wherever you are going.\nWhen the plane lands, you need your stuff, right? So you politely push back toward the back of the plane and the location for your stuff. One you've retrieved your stuff, do you stay where you are, or are the people you've pushed past responsible for letting you make it back to your seat?\nI say you stay where you are. What do you think?\nI thought about this on one of my flights to Buffalo and on the way back I encountered it. I was in the third row and someone needed past me to get her stuff from further back in the plane. When I felt her trying to make her way back, I asked her 'Going back for your stuff?' and she responded, I can't remember exactly what she said, indicating that she was going back but somehow expected to go back to the front rows when she was done.\nThink about it – all sorts of people moved out of the way so she could make her way back. As they let her past, they compressed forward and took up the space she previously filled at the front of the plane. There isn't the room nor the need to let her back up to her original position.\nAnyway, because I'm a stinker, I noticed this and waited for her to begin her move back up to the front of the plane. I felt a tap on my shoulder and her request for me to let her by. I (politely of course) told her that I was trying to get out of her way (by leaving the plane) and she persisted by saying that she needed to get her purse.\nShe completely missed the point that everyone in front of her now were in the process of leaving the plane and that if she stayed in her position, she would quickly be able to collect the remainder of her stuff. Why did she immediately assume that all of us should get out of her way so that she could leave the plane sooner than us? Why was she so important that she had to leave earlier?\nAnyway, she finally got the point and stayed where she was and was able to collect all of her belongings and get off the plane without treating us like she was more important than us.\nIf it's me, I politely ask for help getting me back to where my stuff is then WAIT with everyone else to leave the plane from the position where I ended up. That seems to me to be the only fair way to do it.\nWhat do you think?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Git",
  "date":"Sun Jan 19 2014 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1390176000,
  "url":"/posts/2014/git/",
  "content":"Linus Torvalds created a distributed revision control and source code management system called git: https://en.wikipedia.org/wiki/Git_(software). Git is pronounced like 'get', substituting an 'i' for the 'e' in get. The open source world has embraced it in a big way and it's how you install most anything related to Apache Cordova.\nGit is also an English slang word for 'a silly, incompetent, stupid, annoying, senile elderly or childish person': https://en.wikipedia.org/wiki/Git_(slang). I'm a huge Monty Python fan and learned about git from the (my favorite) Argument Clinic sketch (https://youtube.com/watch?v=kQFKtI6gn9Y).\nI never quite made the connection between the two until recently.\nI've started using git (the source code management system, not the slang word) more and more at work lately as well. I was on the phone the other day with a colleague in London and, during the conversation, he referred to the system as 'jit.' Recognizing that he was from the UK and probably knew about git (the stupid person thing) I had to point out that he was pronouncing it wrong.\nHe replied by telling me that Linus' selection of that word for his software caused a bit of trouble for people in the UK. No surprise there. Apparently, people from the UK will say jit when referring to the software system git to avoid the perception that they were referring to the other application of git. Too funny, people being forced to mispronounce a word in order not to offend.\nIn my conversation with him, I said something like “you know it's git, right, as in Stupid Git?” As I said that I quickly realized I'd made a mistake – and said “wait a minute, isn't Stupid Git redundant?” It sure is. I had to laugh out loud.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Windows Phone 8 Upgrade Foibles",
  "date":"Mon Dec 23 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1387843200,
  "url":"/posts/2013/windows-phone-8-upgrade-foibles/",
  "content":"I've been doing some testing of some Cordova apps on a Windows Phone 8 device AT&amp;T was nice enough to give me earlier this year. I would really like to learn more about developing apps for the device, but there's no time and I work primarily with Cordova anyway.\nAnyway, the device prompted me to do an update the other day and I (stupidly) let it go ahead and do what it wanted to do. When it completed, I plugged it back into my Windows 8 desktop and suddenly the device couldn't be seen by the PC. It would beep and let me know it'd seen the device and was installing the necessary driver, but it would quickly beep again and tell me it couldn't install the driver. Then it would go into an infinite loop and repeat those same steps over and over and over again with no end.\nI did a search and didn't find anything. I switched to another USB port on my system and was able to get it connected. Unfortunately, Visual Studio would no longer talk to the device, so even though the device was recognized, I could not use it for testing Cordova apps in Visual Studio.\nUgh. Probably my favorite expression for 2013.\nAnyway, I spent some time thinking through this and, after reading some internet posts about the Visual Studio error I was getting (a timeout error when trying to load the app on the device) I decided to unregister it as a development device then re-register it using the Windows Phone Developer Registration tool shown in the figure below.\n\nIt worked. Something about the upgrade set the device in a mode that  kept Visual Studio from talking to it. Re-registering it apparently put the device back in a better state.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Schizophrenic BlackBerry Browser",
  "date":"Sun Dec 22 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1387756800,
  "url":"/posts/2013/schizophrenic-blackberry-browser/",
  "content":"Is it me, or is the BlackBerry browser a little Schizophrenic?\n\nWow, that's a lot of personalities.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Sencha Holiday Card 2013",
  "date":"Wed Dec 18 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1387411200,
  "url":"/posts/2013/sencha-holiday-card-2013/",
  "content":"I just received a holiday card (via email of course) from Sencha. Check out the image below - how cool is that? Very Geeky.\n\nI had a chance to do some development with Sencha this year and, once I figured out what I was doing, I really enjoyed it. I liked the ability to define a local store and let the Sencha Proxy manage getting the data back to my server. I owe all of you a big article showing how to build a server process that processes the Sencha Proxy requests, hopefully I'll get to that over the holidays.\nMerry Christmas everyone. I'm not a fan of all that Politically Correct Happy Holidays stuff.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Apache Cordova 3 Programming Now Available",
  "date":"Wed Dec 11 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1386806400,
  "url":"/posts/2013/apache-cordova-3-programming-now-available/",
  "content":"\nApache Cordova 3 Programming is now available for purchase on Amazon.com. Click HERE to learn more.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Apache Cordova 3 Programming Update",
  "date":"Mon Dec 09 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1386633600,
  "url":"/posts/2013/apache-cordova-3-programming-update/",
  "content":"\nApache Cordova 3 Programming is currently available for order from InformIT.\nYesterday, Pearson Education released a sample chapter from Apache Cordova 3 Programming. Click here to access the chapter.\nThe chapter they used is Chapter 6 which covers the mechanics of Cordova development, describing in detail what the Cordova CLI does during the application management process as well as some very useful debugging and troubleshooting tips.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Apache Cordova 3 Programming Pre-Order",
  "date":"Wed Nov 13 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1384387200,
  "url":"/posts/2013/apache-cordova-3-programming-pre-order/",
  "content":"\nApache Cordova 3 Programming is finally available for pre-order. Apparently Amazon has issues with taking pre-orders for eBooks - people expect immediate gratification when they order eBooks, so Amazon won't list it until they have it. In the mean time, I was able to get my publisher to open up pre-orders on its web site, InformIT.com.\nOrder your copy now, they say it will be available before Christmas. A great gift for every geek you know!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Hi I'm",
  "date":"Mon Nov 11 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1384214400,
  "url":"/posts/2013/hi-i-am/",
  "content":"I was reading through the Cordova dev mailing list and noticed that one of the guys had an hi.im (Hi I'm – https://hi.im) URL in his signature. I took a look at the site and saw that it's a pretty cool way to define a simple landing page for yourself. Here's my profile:\n\nNow, when you login, you have a lot of options for what you include in your profile as shown in Figure 2. As I'm using this for my professional persona, there's only a few things I want to add to my profile. For personal use, the list of social networks for example includes all of the common social network options. If you're heavily into social media, you can pepper your profile with a ton of stuff.\n\nSome of the options, such as some of the profile design settings are limited until you upgrade your account. For $20 per year you get more control over the page. It might be worth it, but I'm not ready yet – keep reading.\nAfter I setup my account, I got a nice email from the person who created this site (I'm assuming) welcoming me to the system:\n\nSo I easily added a contact me option to my profile then my linkedin profile. Next I wanted to add my twitter account (@johnwargo) but when I tried to add it, I got the following error:\n\nI've tried time and time again to setup this connection and I consistently get the same error. Doesn't matter what computer I do it from or what browser I use – it's the same thing every time.\nSupposedly they're going to take a look at this shortly, but after weeks of the same error, I thought I'd try to see if they could help me through it. Well, I had an email from Jonathan, right? So I thought I'd let him know about the error. I replied to his email – no response. Next I followed them on twitter and let them know that I've been encountering errors – no response.\nSo, I was going to upgrade my account so I could put images and more stuff on my profile, but as I can't make it work and I can't them to respond to my inquiries, I guess I'm going to have to give up.\nPostscript: I found a help link on the bottom of their home page (those links aren't shown when you login and it takes you automatically to your profile page). I've sent them two emails asking for help with no response. I've also emailed that Jonathan guy who emailed me when I setup my account - no response from my first and second emails.  I know it's a free service, but they'd get my $20 if I could actually make this thing work.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Being Hacked",
  "date":"Thu Nov 07 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1383868800,
  "url":"/posts/2013/being-hacked/",
  "content":"Apparently this site has either pissed somebody off or caught the attention of some bad people. Last night, I got hundreds of attacks against the admin area of the site. Looking at the intruder information, the attacks came from a wide range of IP addresses, so I wonder perhaps if some sort of botnet has been turned against the site.\nWhoever is trying to hack in is trying admin user IDs beyond the normal 'admin' which is a change from the hacking attempts which have been attempted in the past. Normally, I'll see someone try to login hundreds of times using 'admin' as the user name and a variety of words or letter and/or number sequences to get in. This time, the hackers are trying to get in using variants of my name which is an interesting and clearly targeted approach.\nDo people really setup their Joomla sites with admin as the user name and 123456 or 111111 as the admin password? Wow.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "BlackBerry Car Pairing",
  "date":"Tue Nov 05 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1383696000,
  "url":"/posts/2013/blackberry-car-pairing/",
  "content":"I've been carrying a BlackBerry Z30 for a while now and one of the cool things with this latest version of the OS is what happens when you pair the phone with an automobile. During the paring process, the software asks you if this is your car or not. If you say yes, the pairing is labeled 'my car' or something like that. Another interesting thing that happens is that the Bluetooth software knows what kind of vehicle its attached to and shows the car logo on the lock screen as shown below. Not rocket science, but cool none the less.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Apache Cordova 3 Programming Rough Cut",
  "date":"Tue Nov 05 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1383696000,
  "url":"/posts/2013/apache-cordova-3-programming-rough-cut/",
  "content":"\nThe rough cut version of Apache Cordova 3 Programming is now available on Safari Books Online at https://my.safaribooksonline.com/9780133521832.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Repeated Spam, Oh Boy",
  "date":"Sun Nov 03 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1383523200,
  "url":"/posts/2013/repeated-spam-oh-boy/",
  "content":"Got another spam email about my PayPal account. The text (and format of the email looked like it was exactly like the one I'd already written about), even the incorrect formatting of the link text at the bottom of the message. As I started looking at this one, I was able to tell immediately that it didn't come from PayPal. Take a look at this screen shot:\n\nAs you can see from the 'from' address, it's from paypal@services.com. Right away you can tell that the spammers were too stupid to even make it look like it came from paypal.com.\nTake a look at the source of the email message below:\n\nNotice once again that the click URL starts with paypal.com, but the site actually points to what looks like a restaurant web site.  You can see the full URL below with the actual server name highlighted.\n\nSo, once again, just a few seconds of analysis and you can quickly tell that this email certainly did not come from PayPal.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Catching Cordova JavaScript Errors",
  "date":"Sun Nov 03 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1383523200,
  "url":"/posts/2013/catching-cordova-javascript-errors/",
  "content":"If you've done a bit of Cordova development, one of the things that you probably noticed is that in many cases, when Cordova (PhoneGap) fails, it fails silently. This causes a lot of problems for developers because it's not easy to tell what's happened.\nLet me give you an example.\nWhen I read through the PhoneGap support forums, a common problem that occurs regularly is that people complain that the Cordova deviceready event doesn't fire. When I first started working with PhoneGap, my first forum post was about that particular issue. Embarrassing it was, but apparently I had a typo in the &lt;script&gt; tag which loaded the phonegap.js file, so the PhoneGap container simply didn't even fire the deviceready event. A quick change to my JavaScript code to include the correct name for the phonegap.js file (at the time they were labeling each version of the file with a version number like phonegap-1.0.js, and I'd simply added phonegap.js to my app).\nA simple typo, but caused problems none the less.\nAnyway, when the Cordova or PhoneGap container encounters a JavaScript error, it simply aborts whatever it is doing and doesn't tell the user anything. Ugh. I can't tell you how much time I've wasted tracking down bugs caused by this simple error.\nWhen I joined the mobile platform product management team at SAP, I mentioned this problem in a room full of developers and my colleague Istvan Nagy quickly provided me with the solution. If you add the following code to your web application's index.html file, when the application encounters a JavaScript error, it will call fire the window's onerror event and display the error information for the user.\n\nI've started using this in all of my applications as I build them and once I've gotten the application working, I remove it before sending it out to real users.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Weird Cordova Prepare Problems",
  "date":"Tue Oct 29 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1383091200,
  "url":"/posts/2013/weird-cordova-prepare-problems/",
  "content":"I've been having weird problems with the cordova prepare command and finally figured out the problem, so I thought I'd write about it here so others who are having the same problem can hopefully (although hope is not a strategy) find a resolution.\nI'm product manager for an SAP product which is essentially a set of SAP Mobile Platform (SMP) plugins for Apache Cordova. You can read about the product at https://scn.sap.com/blogs/johnwargo/2013/09/22/sap-mobile-platform-and-apache-cordova and https://scn.sap.com/blogs/johnwargo/2013/10/21/an-introduction-to-smp-kapsel.\nAnyways, I'm working on a Kitchen Sink application which shows developers how to use all of the Kapsel plugins and I noticed that some of the plugins simply weren't working. Looking into the problem, it became clear to me that the plugin JavaScipt source code wasn't being copied over to the Android project during the cordova prepare process.\nI'd written this huge (for me) app and had the jQuery and jQuery Mobile libraries, so I thought I was having some timing problems, but the more I looked at it, the more I realized that prepare was simply failing. I turned on debug mode using the following:\n\nPrepare executed as expected and no error messages were returned to the console.\nI scratched my head for a bit then switched over to my development Macintosh and fired up a new Windows VM. I installed all the Cordova and Android parts (having just written a book on the topic, it was quick work) and set about trying to reproduce the problem. No luck. The development environment on the Windows VM worked great, the same environment (I thought) on my corporate Windows laptop didn't.\nYesterday I upgraded node on my system then used npm –g update to update all of my node modules and…the problem went away. Prepare is actually preparing my project as expected. Problem solved.\nSo, when you have Cordova CLI problems and you're not getting information from debug mode, make sure you have the latest and greatest of everything on the node side.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Update on Apache Cordova 3 Programming",
  "date":"Tue Oct 29 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1383091200,
  "url":"/posts/2013/update-on-apache-cordova-3-programming/",
  "content":"\nI finished writing Apache Cordova 3 Programming back in September and now I'm in the production phase with the book. The different sections of the book have been reviewed by several of my colleagues plus several members of the Cordova development team. Right now I'm about halfway through with the copyediting process and hope to have it finished by Monday.\nThe book is not yet available for pre-order on Amazon.com and Informit.com, but the 'paperwork' is in place, so it should be up there any day now. I will post here with links to the ordering pages as soon as something happens.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Spam Message 10282013",
  "date":"Sun Oct 27 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1382918400,
  "url":"/posts/2013/spam-message-10282013/",
  "content":"I've always been fascinated by spam messages. I had a personal email account back in the very early 90's, back in the dial-up ISP days, so I've seen spam from its infancy.\nNotice I'm calling it spam and not SPAM or Spam. In an email context, spam is not an acronym, so I'm truly not sure why people capitalize all of the letters in the word. Spam on the other hand is a tasty breakfast meat (although it can be eaten at any time during the day or night) that I used to have all the time while camping as a boy scout.\nAnyways, spammers have been trying all sorts of tricks to get past filters, and it's always interesting to see how it works inside. This morning I received the following email message.\n\nMy email client recognized the from address, so it let the graphics display (the PayPal logo), but I knew immediately that it couldn't have been from PayPal mostly because I'm pretty sure they'll never email me to tell me that my account has been limited. They might email me to tell me that my account has been disabled, and probably tell me why, but what the heck does “your account has been limited” even mean?\nLooking at the email, you can see that the email content is in a san serif font and the click here link is in a serif font. Clearly the person who crafted this email isn't very good with HTML. Also, in reading the email, you can see it was written by someone who doesn't speak English as a primary language.  For example, the phrase “The account will continue to be frozen until it is approved And Validate Your Account Information” is a dead giveaway as it's not really English.\nAnyway, I always look at the email message source to make sure and when I looked at the source for this message, I found the following:\n\nThe way to tell that this email did not come from PayPal is through the links to resources embedded within the email as well as links to outside entities. For example, as you can see from Figure 2, the logo image comes from a site called jewelleryminx dot com. Hmmm, that doesn't sound like a paypal server to me.\nNotice too the link to 'validate my account info' – this one is the tricky part. If you look at this, you should notice immediately that it looks like it is pointing you to PayPal because the link points to paypal.com, right? Wrong. The link URL begins with paypal.com, but in reality, the URL is a very long and complicated subdomain of givarperu dot org. Anyone who thinks they know what they're doing, including spam filters I think, will see that the URL begins with https://paypal.com and assume it's pointing to PayPal when it is actually pointing to a server registered in Lima Peru, see the domain registration below.\n\nSo, these are a few simple things you can do to tell whether an email is spam or not.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "PhoneGap Day 2013 Presentations",
  "date":"Wed Oct 23 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1382572800,
  "url":"/posts/2013/phonegap-day-2013-presentations/",
  "content":"I had a chance to attend PhoneGap Day in Portland this summer. Now that my day job involves Apache Cordova https://scn.sap.com/blogs/johnwargo/2013/10/21/an-introduction-to-smp-kapsel, I was able to make arrangements to attend. The event was a lot of fun and I learned a lot of interesting stuff about PhoneGap and what people were doing with it.\nHere's a picture of the goodie bag they gave all attendees. My favorite gift was the PhoneGap branded cell phone charger thingie. I love that and I was able to score a second bag and therefore get two of them.\n\nThere were some very interesting sessions. My favorite session was by Lyza Danger Gardner where she covered PhoneGap Self Defense for Web Devs. It was a fast-paced and very interesting session about the things that a PhoneGap (and Cordova or course) developer must keep in mind while developing web applications for the PhoneGap container. It all made perfect sense as I listened to her speak, but it happened so fast that I know I'm going to have to watch it again to make it sink in. This is an absolute must see for anyone building hybrid applications. You can find the video recording of her session at https://phonegap.com/blog/2013/10/18/phonegap-self-defense/.\nThere was another session that is worth noting; not because it was good, but for other reasons I shall try to explain.\nApparently the PhoneGap and Cordova development teams are beer drinkers. So, with much fanfare, they started serving beer beginning at lunch (and throughout the remainder of PhoneGap day). I like beer and I even like drinking beer (on special occasions of course) for breakfast and sometimes even lunch. In this case, I was in a room where a whole bunch of young people had started drinking beer at about 12:30.\nAnyway, I made the mistake of saying something to someone standing next to me after lunch and he manhandled me into a conversation that I wasn't very interested in but consumed a lot of time. Apparently this particular person had had a few beers and that only exacerbated his outgoing personality. Well, it turns out that he was a presenter and he soon went up on stage and delivered what was, in my opinion, the most inappropriate and unprofessional conference presentation I've ever seen (and I even saw John Cleese [of Monty Python fame] say 'asshole' during a keynote at an IBM conference). You can watch the video of his session here https://phonegap.com/blog/2013/10/17/making-real/. Please be forewarned that there's a lot of obscenities in this session and the audio quality is not very good.\nThe slides for all of the sessions (except for Lyza's, rats) are at https://phonegap.com/blog/2013/08/02/a-look-back-at-pgday-us/.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Chinese Translation of PhoneGap Essentials",
  "date":"Wed Oct 23 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1382572800,
  "url":"/posts/2013/chinese-translation-of-phonegap-essentials/",
  "content":"I posted here last year that my PhoneGap Essentials was licensed for translation into Chinese and Korean. Over time, some copies of the Korean translation showed up at my door. It was so amazing to see my work in another language.\nWhat surprised me the most about looking at the translation was that they'd translated the comments in the source code as well. That was the right thing to do, I'd just not expected it.\nAnyway, my new book, Apache Cordova 3 Programming is supposed to go up on Amazon for pre-order this week, so I've been periodically checking to see if it's up there. As I searched Amazon yesterday, I noticed that there was a copy of the Chinese edition of PhoneGap Essentials available for sale (at more than $100 none the less – the book sells for about $5US in China).\nHere's an image of the cover.\n\nMy boss is going to China in a few weeks for SAP TechEd, so I'm hoping I can get one of my colleagues to order it and give it to him to bring back for me. My cousin and his wife are in Hong Kong, so perhaps they can get me a copy. We'll see what happens.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Email Message Layout Revisited",
  "date":"Tue Oct 15 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1381881600,
  "url":"/posts/2013/email-message-layout-revisited/",
  "content":"A while back, I complained about how email marketers weren't taking mobile devices into account when formatting blast emails. They were sending HTML-formatted messages and using CSS to style the emails like they wanted to, but those emails simply didn't render correctly on devices with smaller screens (like the keyboarded BlackBerry devices).\nI know that the people creating these emails were taking mobile devices into account, they'd have to as many people nowadays don't even have PCs anymore, but where I think they fail is in accommodating all types of mobile devices.\nI received a couple of emails today which made me think about this topic. The one shown in Figure 1 below is what started me thinking about this. Notice how the content goes off the right side of the screen.\n\nIn my previous post, I was complaining mostly because the emails I received were centered rather than flush left in the email, so no matter what the device, anything with a screen more narrow than the width of the email would see a lot of blank left border for the email. With the example above, at least they flushed the content left so I wasn't looking at a bunch of blank space on the left with content beginning more toward the center of the screen. It's still not readable, but at least no screen real estate is wasted.\nThat was my point of my previous post – don't waste screen space by unnecessarily centering things. Several people misunderstood my point.\nREI on the other hand, paid special attention to what they did and sent me the email shown in Figure 2 below. Notice how the email renders beautifully? They centered the content, but at least at the same time made sure that they didn't go past the right margin either.\n\nThat's the way to do HTML emails to mobile devices. Deliver an exceptional experience no matter what client is viewing the email.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "BlackBerry Z30 Mail UI",
  "date":"Tue Oct 15 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1381881600,
  "url":"/posts/2013/blackberry-z30-mail-ui/",
  "content":"I've been carrying a BlackBerry Z30 for some time now and I really love it. The keyboard is awesome and the form factor is perfect – much better than the super-silly iPhone.\nAnyway, I do miss the keyboard though. One of the things that has always made the BlackBerry perfect for heavy mail and PIM usage is how the keyboard simplifies so many tasks. Filing a message is as easy as hitting the i key and starting to type the first letters of the folder name and you can file the message in no time. When filing subsequent emails, the last folder used for messages from that thread appears as soon as you press the i key. Android and iOS make this as hard as possible by not allowing you to bring up a keyboard while filing a message. Ugh.\nAnyway, as I've been using the Z30, I've noticed how they don't make it easy to delete messages after you've read them. There's no delete key (because there's no physical keyboard) and they don't expose the delete button in the default UI shown at the bottom-right of the following figure.\n\nIf you want to delete a message, you have to tap that three-button more thingie (whatever that is) and select delete from the menu that appears. Inconveniencing, but I'm OK with it. Although I would argue that delete would be used a lot more than the Search button, so they could switch the position of the two and make a LOT of users happier.\nAs I looked at the screen, it occurred to me that perhaps if I turn the device sideways, the delete button I need so much would appear (since there's much more room in landscape mode). So, I rotated the device then took the screen shot shown below.\n\nNotice that with all of that additional available real estate, all they did was expand the distance between the buttons. What a waste. With all of that extra room, what I expect is that the most used items from the menu will drop down into that lower menu and be available to me in one click instead of two. Nope, they didn't do that.\nThis is another example of what happens when developers don't think about how users will actually use their software. It's easier to keep the same buttons rather than make use of the additional space. Too bad.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "My Day Job at SAP with Kapsel",
  "date":"Mon Oct 07 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1381190400,
  "url":"/posts/2013/my-day-job-at-sap-with-kapsel/",
  "content":"In case any of you were wondering, in my day job I am a product manager for the SAP Mobile platform. I'm currently working on products that use or plugin to Apache Cordova. Earlier this week I recorded an SAP Code Talk with my colleague Ian Thain where I talk about Cordova and what SAP is doing with Cordova.\nRight now I'm working on a product called Kapsel which is a set of SAP plugins for Apache Cordova and is part of the SAP Mobile platform. Kapsel essentially allows a developer to more easily build a Cordova application which consumes enterprise application services exposed by the SMP server. I'll be writing more and more about Kapsel on my SCN blog (see the sightings area of the site) over the next few months.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Nexus 7 Setup on Windows",
  "date":"Thu Sep 26 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1380240000,
  "url":"/posts/2013/nexus-7-setup-on-windows/",
  "content":"I was trying to test a Kapsel application yesterday on my Nexus 7 and was having some problems (Kapsel is a set of SAP plugins for Cordova that I wrote about on my SCN Blog here https://scn.sap.com/blogs/johnwargo/2013/09/22/sap-mobile-platform-and-apache-cordova). Essentially, I was trying to install the application on the device via a USB cable, but my Windows system wasn't recognizing the device. The device saw that it was connected to the Windows system and prompted me to enable USB debugging, but Windows was 'seeing' the device, but couldn't really talk to it.\nI'd encountered this problem while working on Apache Cordova 3 Programming and figured it out, but for the life of me I couldn't remember how I'd done it. I of course grabbed the manuscript and looked to see if I'd documented the solution to the problem and of course I hadn't. So, I thought I'd write about it here then I'll put a link in the book that points to this article.\nOK, so when I plugged the device in, Windows twirled and whirled for a while trying to install the appropriate device driver. After much work, it finally decided that it couldn't do so and displayed an error message. When I looked at the Windows Device Manager, I noticed what is shown in the following figure, that it recognized the device, but simply didn't know what to do with it. Notice under 'Other devices' that the Nexus 7 is listed.\n\nSo, I knew that Google provides special USB device driver as part of their SDK, so I fired up the SDK tools and made sure to select the Google USB Driver as shown in the following figure.\n\nWith that in place, I was ready to fix this problem. In Windows Device Manager, back in Figure 1, I right-clicked on the Nexus 7 entry and from the menu that appeared I selected Update Driver Software. In the dialog that appears, I selected Browse my computer for driver software as shown in the Figure 3.\n\nNext I was prompted to identify where Windows should search for the driver. I could have let it search the whole drive, but I knew that the driver I wanted was likely in the folder where I'd installed the Android development tools (ADT), so I simply pointed it to that folder then clicked next to begin the search.\n\nAfter a while, it found the driver, installed it then displayed the results screen shown in Figure 5.\n\nClosing the dialog and looking again at the Windows Device Manager as shown in Figure 6, you'll see that the Nexus 7 is now recognized by Windows as an Android Composite ADB Interface device.\n\nWith this completed, I was able to install the application onto the device using the Android command line tools.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "A Day in the Life",
  "date":"Sun Sep 22 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1379894400,
  "url":"/posts/2013/a-day-in-the-life/",
  "content":"A few months back I was looking at some marketing material for one of our competitors (I don't really remember which one, but I think I have an idea) and noticed the following graphic portraying a day in the life of a mobile worker.\n\nWhat struck me as interesting is how they portray the different systems this mobile worker uses throughout the day. I understand having a laptop, smartphone and tablet. I expect the smartphone to be used while in motion, the tablet used when more time is available or when more 'stuff' needs to be done and laptop when heavy typing, creative work or just high quantity of mail filing (iOS is horrible for enterprise mail use simply for that reason alone) is needed.\nSo the worker starts the day on his or her Android smartphone, switches later to a laptop, then tablet, then a desktop? Really? Desktop AND laptop? Next they fire up a Windows 8 device then wrap up their day with the Android smartphone again?\nThat's not how it works is it? It's highly unlikely that the worker is going to have access to a desktop and a laptop – I expect that in today's economy that the user is expected to connect their laptop when in the office to do work, not use a desktop that's sitting there waiting for him to use it.\nFrom a tablet standpoint, is the employee really going to have both an iOS tablet and a touch-screen Windows 8 device? I think not. Very few organizations are fiscally irresponsible enough to do that.\nI understand what they're trying to do, highlight all of the different targets they support, but highlighting all of them as an example of a day in the life of a mobile worker makes no sense. The same story can be told much more effectively by highlighting multiple employees and showing all of the possible ways these employees will need to work with their productivity applications.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Silly Bank of America Web Site",
  "date":"Sat Sep 21 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1379808000,
  "url":"/posts/2013/silly-bank-of-america-web-site/",
  "content":"I was on the Bank of America web site the other day using my BlackBerry Q10 device and noticed something interesting as shown in the following figure. The web site recognized I was on a mobile device and for some bizarre reason decided to rotate the page sideways.\n\nI'm trying to figure out the user story or requirements that drove them to implement their site this way. I'm not a fan of an operating system or web site making decisions on my behalf. If I was on a touch-only device like the BlackBerry Z30, then rotating it sideways would not be what I wanted, but would at least be useable. Since this was a Q10 and has a full keyboard, rotating the page like they did actually makes the site quite unusable; I won't be able to read the screen while typing anything.\nUgh.\nNow, they know I'm on a BlackBerry device and kindly offered me a link I could use to download their mobile app.\n\nUnfortunately, they don't offer an app that is compatible with my particular device as shown in the following figure. Why even offer me a chance to download an app for my device when you know what device I'm using AND you also know that there IS NO app for that device?\nUgh again!\nI was actually using their site because I needed to find an ATM and knew there wasn't an app for my device, I'd already checked. I happened to be in Akron, Ohio and was looking for an ATM nearby. Here's the results they delivered for my search:\n\nNow I know delivering no results is problematic, just in case I am willing to drive some distance to find the particular ATM, but looking at the figure, do they really think I'm going to drive almost 100 miles to use one of their ATMs? Paying a $2 fee to use another bank's ATM would be a much better option for me than to drive 99 miles. In my car, if the trip was 100% highway, that would be at least $12 in gas for me to use that ATM.\nThinking through this, I'm imagining that a survey of their users would tell them that most people probably have a 25 mile or highly unlikely but possible 50 mile distance they would be willing to drive to locate a store, but an ATM? I don't think so.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Item",
  "date":"Thu Sep 19 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1379635200,
  "url":"/posts/2013/item/",
  "content":"A while back, my brother in law gave me the item shown in the figure below. I'll let you take a look at it for a minute before I tell you what it is.\n\nAs soon as he handed it to me, he asked me 'do you know what this is?' Of course it did, it's an F-bomb. Get it?\nAnyways, what's funny about this and the reason for me writing this article is that a quick survey has shown me that some people get this instantly but others simply can't make the connection. Apparently my BOL asked my brother and he had no clue, his PhD wife walked by and said “that's an F-bomb.” My wife looked at it and couldn't figure out what it was and, once she learned what it was, immediately said “I don't think of a hand-grenade as a bomb” I don't know what else it could be, but OK.\nI tweeted a picture of this last week after I hung it and when I saw one of my neighbors, a very smart neighbor, she immediately said “I give up” – she couldn't figure it out. Another neighbor walked up and she got it within 2 seconds.\nI guess it's all about how your brain is wired (and perhaps how dirty your mind is).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Launched Cordova Programming Web Site",
  "date":"Wed Sep 18 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1379548800,
  "url":"/posts/2013/launched-cordova-programming-web-site/",
  "content":"\nToday I launched the web site for my upcoming book called Apache Cordova 3 Programming; you can find the site at cordovaprogramming.com. The book is written but still going through the editing process. stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "My Fifth Book",
  "date":"Mon Sep 16 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1379376000,
  "url":"/posts/2013/my-fifth-book/",
  "content":"\nA few minutes after finishing my 4th book, I received an email from the editor at The View letting me know that they'd published an anthology of their mobile development articles called Mastering Mobile for Notes/Domino. The book is essentially a collection of 22 articles and 16 of them are mine, so 72.73% of the 'chapters' are my work. You can find information about the anthology at The View.  If you order a copy, please tell them you heard about it here!\nI didn't do a page calculation to figure out exactly how much of the book is my writing, but I'm still going to count this as a book I've 'written' a part of.\nOver the years, I wrote 20 articles for the view and 18 of them were on mobile development. During that time, I usually wrote something here about the articles and many readers reached out to me for access to the article content. Since I don't own the content, I couldn't make any of it available. Now however, even non-subscribers have access to the content. So, if you've wanted to read some of my mobile development articles for IBM Lotus Domino, you can access most of them through this anthology.\nEnjoy!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Apache Cordova 3 Programming",
  "date":"Mon Sep 16 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1379376000,
  "url":"/posts/2013/apache-cordova-3-programming/",
  "content":"\nLast week I put the finishing touches on Apache Cordova 3 Programming, my 4th book. The Cordova team recently released version 3 of the popular open source mobile development framework and this should be the first book on the topic.\nThe book is essentially a rewrite of the first half of PhoneGap Essentials. The Cordova tooling changed dramatically after PhoneGap Essentials was published, so the first half of that older book was pretty out of date. The first chapter is essentially the same, while the rest of the book focuses primarily on the tooling, but the last 100 pages cover the Cordova APIs, creating plugins and the end to end development process. It's complete coverage of the topic, but simply doesn't go into the APIs in as much detail as PhoneGap Essentials did.\nIn PhoneGap Essentials I wrote in detail about all of the supported mobile device platforms, but in this book, I focused only on Android, BlackBerry 10, iOS and Windows Phone 8. Additionally, PhoneGap Essentials didn't contain anything about PhoneGap or Cordova plugins, so in this edition I added a chapter where I create two plugins, one which is JavaScript only (for educational purposes) and another which is a native plugin for Android and iOS.\nI'm pretty excited about the book; it's about 300 pages and should be out in electronic version pretty soon and available as a printed book before Christmas. I will post an update on the site as soon as it's available from my publisher at informit.com and amazon.com. Right now the book's web site is not operational, but I will fix that by the end of the week.\nI really want to do an update on the second half of PhoneGap Essentials, so I'm having a discussion with my publisher about that as well. Stay tuned, I'll let you know how this progresses.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Amazon Shipping Problems",
  "date":"Sun Aug 25 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1377475200,
  "url":"/posts/2013/amazon-shipping-problems/",
  "content":"I wrote a few weeks back about some shipping problems Amazon seems to be having. It's gotten worse, I recently ordered a CD from No-Man, a side project of Steven Wilson. I received the disc last week, but Amazon thinks they're getting ready to ship it any minute now as shown in the figure below:\n\nI'm not sure what to do. Do I cancel the order? No, can't do that as it would be unethical. Do I let them ship it to me again? No, that would be wasteful and, if I try to refuse it or return it, they'll probably credit me back again. Ugh.\nI could try to contact them, to tell them it's shown as not shipping yet but I already have the item, but they're online help isn't setup for that scenario.\nI'm going to have to submit a support ticket, but why is it my responsibility?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Using Joomla K2",
  "date":"Sat Aug 24 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1377388800,
  "url":"/posts/2013/using-joomla-k2/",
  "content":"I've started work on the web site for my upcoming book, Apache Cordova Programming.\nFor my BlackBerry Development Fundamentals, I created the site using Joomla. For PhoneGap Essentials, I wanted to learn Drupal, so I used it to build the book's web site. For my What Now? The Essential Guide for New Soccer Referees, I used the Concrete 5 CMS. Since I've used a different CMS for each book's web site, it would be cool to continue the tradition, but no other CMS has caught my eye. I wanted to try to use Xoops for something, but that one seems to have withered on the vine.\nDrupal is very powerful, but a little hard to work with. You have great power in what you can do with a site, but I found it to be pretty slow and cumbersome. Unfortunately, for the type of site I wanted to build for PhoneGap Essentials, Drupal was a great choice as the very powerful Content Creation Kit (CCK) was moved into the core of Drupal beginning with Drupal 7. The CCK allowed me to easily define custom fields for my different content types and render and sort by those fields in views. It was pretty cool and I was able to quickly do what I wanted with the site – customizing the Chapters and Errata views on the site.\nI'm a super big fan of Joomla, and although Drupal would give me the flexibility I needed to make the site I needed, I would really prefer to do it with Joomla. So, I registered a domain, setup a Joomla site (using the latest and greatest version of course) and started looking for a way to get the CCK capabilities I wanted with a Joomla-based web site.\nIf you search through the Joomla Extension Directory and look at CCK extensions, the JoomlaWorks K2 extension is listed as one of the most popular. I looked around on their web site (https://getk2.org) and it looked like it had everything I needed. I installed it and figured out how to use it fairly quickly although there is absolutely no documentation available for the extension. There are video tutorials, but no documentation at all that I can find. After playing around with it for a while, I was frustrated to find that it really doesn't provide the capabilities I need. It works (sort of) and it has a pretty cool set of features, but falls down in the critical places where I need it the most.\nI was able to add extra fields like Chapter and Page, and built some field groups to group them together.  My Chapter content needed the Chapter field, but the Errata article type needed both Chapter and Page. Unfortunately, for some bizarre reason, you can't have a field in two field groups. Makes no sense to me, but that is the way it works. So, I had to add a Chapter field for the Chapter article type and another Chapter field for the Errata article type. Ugh.\nThere's no numeric field type. I can add a bunch of extra fields, but not numeric fields. If you look at the previous paragraph, doesn't Chapter and Page Number fields imply they're numeric? Nope, had to create them as text, not numeric fields. Next to useless.\nK2 doesn't seem to support any custom views. Now that I have all of my chapter content entered with my shiny new Chapter field added, I want to create a view that allows me to render articles sorted by chapter number. Nope, can't do it. Not only can't you show a custom field in a view, you can't sort on it either. What's the sense of allowing me to add additional fields to an article if I can't use them for anything.  And, since I have to use text fields instead of numeric fields, even if I could use them in views, they would still sort as 1, 10, 2, 3 and so on since that's the way sorting by textual numbers works.\nWhat's the point?\nIt seems like they expect you to extend Joomla's article system in order to create custom views, but that seems like more trouble than it's worth. I've printed out a tutorial on the topic and we'll see over the next couple of weeks if I can figure it out.\nI tried using the Article Manager to force the order of the Chapter articles, but could not make it work any way I tried. The default Joomla article manager allows me to do it, but not K2.\nOver the last few months, I've posted some questions to the K2 forums. When I'm up there looking around, there's nobody else but me up there, so it really feels like an unpopular or near death extension.\nI've posted question on the forums asking how I can create custom views. I've asked where the documentation is.  I've asked why there's no numeric field type. No response. I did get one response, but the responder used Google Translate to translate my question and the response I got back (translated back into English) was incomprehensible.\nIt sure feels like K2 is near death. It has great aspirations, but simply doesn't deliver. Too bad, it looked like a good option for me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "What Were They Thinking 14",
  "date":"Sat Aug 17 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1376784000,
  "url":"/posts/2013/what-were-they-thinking-14/",
  "content":"OK, so I was registering my daughter for fall Soccer (That's Football to most of the world) at the local YMCA. The person behind the counter scanned my membership card, so had all of the information she needed to complete the registration except for payment. Actually, that's not true – they automatically transfer the monthly fee from my checking account, so they even had the information they needed to collect payment as well.\nAnyways, knowing they had everything they needed to register my daughter, they still handed me an iPad with an application I needed to use to fill out her registration. Mind you, they scanned my membership card then validated my name, email address, mailing address and more plus identified the child I wanted to register by name – but still needed me to fill out this form on the iPad.\nWhat a bunch of idiots.\nAnyway, I'm filling out the form with my daughter's name and my contact information and one of the fields that I need to fill out is her birth year. I clicked the dropdown and saw that the very first year on the list was 2037.  Yep, it's 2013 and they START the birth year at 2037 and go down from there.\nAssuming the sports program starts at 4, it would have to be 2041 before that year would apply.\nDid I mention that they're a bunch of idiots?\nI'm not sure, but do you think the developer who built the application could have done a little math and done the following:\n\nThis is just another find example of a mobile application developer not thinking as they work on an application.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "Surprise Amazon Shipment",
  "date":"Sat Aug 03 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1375574400,
  "url":"/posts/2013/surprise-amazon-shipment/",
  "content":"I received a surprise Amazon shipment the other day. SAP recently released a product SAP Mobile Documents and as its standards-based I wanted to learn more about the underlying technology so I ordered a copy of CMIS and Apache Chemistry in Action. When the package arrived, there were two boxes. I was expecting one box, so the second one surprised me.\nI opened both and one was my copy of CMIS and Apache Chemistry in Action and the other contained Guitar for Dummies. I don't play guitar, so that particular book surprised me a bit. I hadn't ordered the book and I wasn't expecting a gift from anyone. The packing slip didn't have much on it except for an order number, so I looked up the order number and couldn't find it. I initiated a chat with Amazon customer service and apparently the order belonged to someone else. I'm not quite sure why they put it in a package and addressed it to me, but there it was.\nEven though I told Amazon that I hadn't ordered it, they took a while and finally determined that it wasn't mine and I'd not ordered it. No surprise to me, but apparently they had to double verify that the package they sent to me wasn't for me.\nAnyway, I expected that they'd email me a shipping label and thank me for sending it back to them.\nNope, that's not what happened\nThey told me I could keep it. Apparently there's no way for Amazon to generate a shipping label and send it to a customer if the order the shipping label is for is not on the customer's account.\nNo, seriously – that's what they told me.\nThey have one of the most sophisticated and automated online and warehouse management systems in the world and they can't fix it when one of their folks ships me something I didn't order. That's quite a systems problem they have – rather than simply enable customer service reps to order ad-hoc shipping labels, they let me keep an item they sold for $20 or so.\nWhat's funny is that this isn't the only time this happened to me. Last week I ordered some CDs from my wish list (some Dream Theater, Tony Iommi and Ian Gillan) and they shipped it to me, it never arrived and they shipped it to me again. Apparently the exact same thing happened with my order – they picked it, but shipped it to someone else. What's funny about this is that about a week later I got an email from Amazon Customer Service telling me that they were unable to deliver a package to me. Even though they send me packages all the time and the address they have on file for me is spot on, they suddenly couldn't find me.\nIt all worked out, my son's learning guitar, so I gave the book to him.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "ChargeCard Smartphone Charger",
  "date":"Sat Aug 03 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1375574400,
  "url":"/posts/2013/chargecard-smartphone-charger/",
  "content":"I was reading through one of my tech magazines the other day (I can't remember whether it was PC Magazine or Popular Science, sorry) and noticed this cool charger cable called ChargeCard. I used to travel a lot and bring a bunch of cables and so on with me in a little pouch. Over time, the pouch has gotten bigger and bigger and now, with all of the devices I carry with me, it looks like this:\n\nAnyways, the ChargeCard is a single, credit card-sized piece of rubber/plastic that includes two USB connectors. There's a micro USB connector for your standard BlackBerry, Android device and so on plus there's a USB Type A connector for plugging into your laptop or PC USB receptacle. The card is about the thickness of two credit cards and looks like this:\n\nThe exposed micro USB connector plugs into most any modern smartphone except for any iOS product. The PC USB connector is made of a flexible rubber-like material which allows you to bend it out of the card and insert it in the appropriate USB receptacle on your PC.\nIt is pretty cool and takes up a whole lot less room than my assortment of cables. It is super small, so I can easily fit it in my bag and take it anywhere with me.\nIt's a little pricy at $25, but well worth it when you consider how small and useful it is.\nFor those devices that don't use a standard micro USB connector (that would pretty much only be iOS devices, too bad) the ChardgeCard folks also make a ChargeCard for those devices as well. It's not their fault, but if you carry both an Android and iOS device, you'll need to carry two ChargeCards with you in order to be able to charge both. Fortunately they're very small, so carrying two of them still takes up less room than a single, traditional USB cable.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Cordova DeviceReady Firing",
  "date":"Sun Jul 28 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1375056000,
  "url":"/posts/2013/cordova-deviceready-firing/",
  "content":"A colleague taught me something recently that I didn't know about the Cordova deviceready event. This is probably default JavaScript event behavior, but I was just unaware of it. When you register an event listener, if the event has already fired, registering a new event listener will cause the new event listener target function to fire.\nI'm not sure how useful this information is, but I had to test it out to make sure it worked as I expected it to. In the sample application below, I have a simple Apache Cordova application that initializes then displays a page with a button on it. When you click the button, the application registers the deviceready event listener (which has already fired by the time the user can click the button) which causes the myNewFunction() function to fire immediately. Cool, eh?\nHere's the code:\n\nHere's the application running on an iOS simulator.\n![Sample Cordova Application Running on an iOS Simulator\nAnd here's the output from the application's call to console.log.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Canadian Out of the Office",
  "date":"Mon Jul 01 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1372723200,
  "url":"/posts/2013/canadian-out-of-the-office/",
  "content":"One of my Canadian colleagues was out of the office on Monday and she had the funniest OOO message I've ever seen:\nI am out of the office on Monday July 1 to celebrate Canada Day. I will have no access to email or voicemail and will be back in the office on Tuesday July 2.\nHere are some fun facts about Canada that you may not already know:\n\nThe Stanley Cup has its own bodyguard, but that doesn't mean Canadian hockey champions haven't put all kinds of different foods and drinks in it (everything from chocolate milk to popcorn and cereal!)\nBritish Columbian pioneers made use of the oolichan, also called candlefish, at nighttime. The small fish is so fatty that it can be dried, strung on a wick and burned like a candle!\nCanada's name comes from a misunderstanding between Jacques Cartier and some Iroquois youth who were pointing out a village (for which they used the word “Kanata”). They were actually trying to identify the small area which is present day Quebec City, but Cartier used the similar-sounding word “Canada” to refer to the whole area. Oops!\nThe Narcisse Snake Dens in Manitoba have more snakes in a concentrated area than anywhere else in the world. Tens of thousands of red-sided garter snakes gather there every year. On the other hand, there are no snakes on the island of Newfoundland.\nCanada officially got its own national flag on February 15, 1965 — almost 100 years after it became a country (in 1867).\nCanada's official languages may be French and English, but our geese have their own language: scientists believe that Canada geese have as many as 13 different calls for everything from greetings and warnings to happiness.\nIf you visit Dawson City, Yukon, you can join the “Sourtoe Cocktail Club” — all you have to do is finish a drink (of anything!) with a real human toe in the bottom. The club's motto says, “You can drink it fast, you can drink it slow — but the lips have gotta touch the toe.”\nIn 1962, Pincher Creek, Alberta experienced the fastest, biggest temperature change ever recorded in Canada as a result of a Chinook (a warm, dry wind that comes off the Rocky Mountains). The temperature rose from -19C to 22C in just one hour!\nBetween 1984 and 2008, it was illegal to sell pop (this is 'soda' for Americans) in cans in PEI. All carbonated drinks had to be purchased in refillable glass bottles. PEI was the only place in North America to have a “can ban.”\nForget the Loch Ness Monster: Canada has its own mysterious lake creature, Ogopogo, who reportedly lives in Lake Okanagan, British Columbia.\n\nAnd my absolute favorite fact: Canadians consume more mac and cheese than any nation on earth (source: https://canadiangeographic.ca/kids/fun-facts/).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Leaving The View",
  "date":"Wed Jun 19 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1371686400,
  "url":"/posts/2013/leaving-the-view/",
  "content":"Back in 2010, The View magazine approached me and asked me if I was interested in becoming a technical advisor to the publication. Being a long-time IBM Lotus Domino developer (a really, really long time) and a speaker at several View Domino Developer conferences, I of course said yes. We spent some time discussing what they needed from me and we decided that a series of articles on mobile development for Domino would be a great fit for my area of expertise. I was onboard.\nI spent some time thinking about some articles I wanted to write and I solicited some articles from mobile developers I knew. Before long its three years later and I've published 20 articles for the magazine (the official 20th one was published last week) and advised on some articles from other authors. It was a great relationship and a lot of fun. At times, I'd have multiple articles in a single edition of the print version of the publication. I even got an article into their best of 2011 Anthology which was distributed at Lotusphere 2012.\nOver time though, I moved further and further away from the IBM Lotus Domino space. My last real work with Domino ended in 2006 after I'd left Wolcott Systems Group (where I created the award winning Automated Deployment Toolkit for Lotus Notes) and wrapped up a few independent consulting engagements. After that I went to work for RIM (now called BlackBerry) and tinkered a bit with Domino and BlackBerry.  At that point any official connection to Domino development ended and it was just a hobby.\nWhen I worked at AT&amp;T, they were kind enough to let me dabble in Domino development and speak at some Domino development conferences (the View conferences of course, plus several MWLUG conferences). Now that I'm at SAP, there's really no way for me to continue to work with Domino. I can't justify it in my new role as a product manager for the SAP Mobile Platform (SMP) and I'm simply too busy with my day job working on the platform along with my side job of writing Apache Cordova/Adobe PhoneGap books.\nA few months back I had a conversation with my new editor at The View and discussed a few article ideas I had. As we talked about it, I really didn't have anything new and interesting to write about. They were looking for more stuff on Xpages and I didn't have the skills (or the time to get them). At the end of the conversation we decided that the final article in the Sencha Touch series would be my last for the publication.\nI'd always wanted to see the article series published into a book. Take my articles and add some of the other mobile development articles that were published and make an 'everything you ever wanted to know about mobile development for Domino' book, but I doubt that will ever happen. If it does, it'll make my day (and be my 5th book, my 4th on mobile development)!\nI'm beginning discussions with the editors of some of the View's sister publications on SAP technologies; but who knows where I'll end up next.  I do love to write. I'll have a new book coming out before the end of the year and hopefully another one early next year.\nAnyway, it's been a fun run and I've really enjoyed sharing my Domino mobile development experiences with all of you.  Stay in touch!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "You can always tell...",
  "date":"Tue Jun 18 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1371600000,
  "url":"/posts/2013/you-can-always-tell/",
  "content":"You can always tell when I'm busy with something by how long it's been since I've updated the blog. I've got this big list of articles to write, but just can't seem to get to them.\nAt work, I've joined the Product Management Team for the SAP Mobile Platform, so that's keeping me very busy. I can't talk about what I'm working on yet, but I'll do some writing about it soon.\nI learned recently that my PhoneGap Essentials book is the leading book on the topic (as far as sales numbers indicate). That's great to know and prompted my publisher to ask me about doing an update. We decided to do an update to the tools part of the book and I'm about a third of the way through writing the manuscript. I'll let you know more about the update as soon as I have the title finalized, a cover and its available for pre-order on Amazon.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Weird Spamming",
  "date":"Thu May 23 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1369353600,
  "url":"/posts/2013/weird-spamming/",
  "content":"Just got a weird inquiry from my BlackBerry Development Fundamentals web site. I'm sure it's spammers, but I'm not sure what they're trying to accomplish. Either I'm completely missing the point of this or whoever is trying to spam me knows nothing about the English language. Links removed for protection:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "BlackBerry Facebook Application Broken",
  "date":"Mon May 13 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1368489600,
  "url":"/posts/2013/blackberry-facebook-application-broken/",
  "content":"Something's up with the latest version of the Facebook app for BlackBerry. Parts of the UI simply don't work and I don't know how to let BlackBerry know about it. Apps like TeleNav Navigator have a feedback function which allows you to let them know when something doesn't work or if you have suggestions for the application. All of the different mobile OS are adding APIs for Twitter, Facebook and so on, why not add a feedback API that allows an app to send customer comments/feedback to the developer? No sense in each developer writing their own when it can simply be a default API on the device.\nAnyway, to my problem! If you look at Figure 1, you'll see the standard Facebook home screen running on my BlackBerry Bold 9930. Notice the three images at the top center (in the blue bar). What it's showing me is that there are three 'view's available here and that one of them has new items.\n\nFigure 1\nUnfortunately, when I tap on one of those images (or even click on them using the touch pad that the Bold 9900 still has) nothing happens as shown in Figure 2. I can click on that image repeatedly and nothing happens except that the image gets highlighted.\n\nFigure 2\nSame thing with the little globe icon – click on it and it highlights but doesn't change anything on the screen.\n\nFigure 3\nI can click on the chat icon and see the messages that have been sent to me by my friends, but clicking on either the people or globe icons does…nothing. Are any of you experiencing the same issue? Any suggestions on how I can let the folks at BlackBerry know and hopefully get a fix?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "What Were They Thinking 13 – VZ Navigator",
  "date":"Mon Apr 29 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1367280000,
  "url":"/posts/2013/what-were-they-thinking-13-vz-navigator/",
  "content":"While I worked at AT&amp;T, I became a big fan of the TeleNav Navigator application which later became AT&amp;T Navigator. The interface was intuitive and it worked pretty well. When I joined SAP, they gave me a Verizon BlackBerry 9900 and I lost access to the navigation solution I was accustomed to using. On Verizon, they have their own navigation solution called VZ Navigator; here's what it looks like:\n\nI was using it recently to navigate somewhere and noticed something about the UI that really struck me as stupid, so of course I had to write about it here.\nWhen you press the volume buttons on the side of the device to increase or decrease volume, instead of actually increasing or decreasing the navigation volume (which is what ANY smartphone user will expect), the application instead opens up the dialog shown in Figure 2.\n\nThis is simply the wrong way to implement this interface, and, to make matters worse, you can't use the volume controls (those buttons on the side of a BlackBerry device) to move the selection on this dialog. I thought perhaps they simply made a mistake by implementing this dialog, but they compounded their error by forcing me to physically touch an item to make a selection rather than to just allow me to use the volume buttons to move the selection down and up on the screen.\nThink about the use case – I'm driving my car and using this application to help me get to my destination. There's  background noise in the vehicle, so I'm trying to increase the volume so I can hear better – and the application forces me to take my eyes off the road and make a selection on the screen rather than to simply use the buttons that BlackBerry put on the device to allow a user to adjust output volume. What this 'feature' does is make the application more difficult to operate and deliberately creates a safety issue for the user (and the occupants of the vehicles around the application user).\nAll the developer had to do was register a listener for the two volume buttons and act accordingly. The developer did register the listener, but instead of implementing expected behavior, they instead broke the application by implementing an unexpected and difficult to operate dialog. This makes no sense to me.\nThe market in general hates BlackBerry applications, but it's not BlackBerry's fault that this application is unusable – they provided all of the features the developer needed to make this application as functional and beautiful as similar applications on Android, iOS or Windows. The developer is the one that made this application less appealing.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "The Solution to My Domino Server Configuration Problem",
  "date":"Thu Apr 18 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1366329600,
  "url":"/posts/2013/the-solution-to-my-domino-server-configuration-problem/",
  "content":"Thanks to all of you who helped out last week as I struggled to get my IBM Lotus Domino server to accept HTTP PUT and DELETE requests. I posted two articles about my issues, you can access them here:\n\nDomino Server 405 Error\nUpdate on My Domino Server Problems\n\nEssentially, I was building a sample Sencha Touch application for an article series I'm writing for The View and the Sencha Touch proxy by default uses different HTTP request types for each of the CRUD operations. The Domino server was refusing PUT and DELETE even though there were settings in the Domino Directory which enabled the server to accept them as shown in the following figure:\n\nThe answer came from Stephan Wissel who said:\n&quot;... the classic Domino agents to GET/POST not Put. After you allow it you need to have an endpoint that actually handles PUT. A servlet does that. XPages might since it is a servlet (haven't tested it). Classic agents don't. Probably it is easier to reconfigure your app to use POST?&quot;\nand Nathan Freeman who said:\n&quot;It spells it out right there in the popup on the label for &quot;Methods.&quot; You have to write your own Java servlet to handle PUT and DELETE. The native HTTP server simply doesn't process them at all. The checkbox is there just so the web server will accept those methods on the assumption that it's passing the request to a CGI or Java program that can handle them.\nYou'll have to write a servlet to do what you're trying to do.&quot;\nSo when I enabled the settings shown in Figure 1, all it seemed to do was allow the requests to pass through and I was responsible for implementing a servlet to deal with those requests. Yeah, I'm not doing that.\nSo,  I turned to the Sencha Touch Proxy configuration to see if I could change the way it worked to get around this limitation in the Domino server. When I started the process, I had a very simple proxy configuration as shown in the following code segment:\n\nLooking through the docs, I found that I could add an actionMethods property to my proxy as shown below:\n\nWhat this does is configure which HTTP methods are used for each proxy action type. OK, that seemed cool although it didn't get me all the way there. See, when you change the actionMethods property, you lose the ability to easily detect the CRUD operation on the server side. This doesn't change the URL passed to the Domino server, it only changes the HTTP method used to get to the server.\nSo, what I had to do next was use the proxy's api property to specify the URL format to use for each request as shown below:\n\nWith this in place, I had now configured the proxy to send a differently formatted URL with each request type.  That was exactly what I needed; now I simply had to parse the URL on the server to be able to tell what the Sencha Touch proxy was asking me to do.\nNote: at about the same time I found these settings in the Sencha Touch documentation I received a comment on the site from Jack Ratcliff with a pointer to these settings. Thanks Jack.\nSo, at the end of all of this, here's what the Sencha Touch proxy configuration looked like:\n\nWorked like a champ! Thanks everyone.\nI'll be finishing up the article this weekend and hopefully you'll see the results in The View in a few weeks.\nYou may be wondering why only the update and destroy commands have the trailing ampersand - you'll have to read the article to see why (sorry).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino",
  
    "JavaScript"
  
  ]
  },

  {
  "title": "Calatrava",
  "date":"Mon Apr 15 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1366070400,
  "url":"/posts/2013/calatrava/",
  "content":"My publisher told me about a cross-platform mobile framework today called Calatrava (https://calatrava.github.io/). I still need to do some reading about what it really is, but something in the announcement caught my eye:\n&quot;Mobile is the oncoming train of the future of computing. For more and more users their mobile device is becoming their first way to reach everything on the Internet. You need to be on-board with this. But there are three platforms to support: iOS, Android and Mobile Web.&quot;\nI'm surprised – I wasn't aware that there were only three platforms a developer needed to target for their mobile apps. It does surprise me sometimes how much ignorance there is in the world.\nAnd mobile an oncoming train? Where have they been - the train has stopped in the station, refuelled and picked up a bunch of passengers. Heck, it's halfway to its next destination.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Update on My Domino Server Problems",
  "date":"Sat Apr 13 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1365897600,
  "url":"/posts/2013/update-on-my-domino-server-problems/",
  "content":"Thanks to all of you who helped out last week trying to help me fix my Domino configuration problem.  Tom Verleysen and Michael Dudding suggested creating an Internet Sites document which I thought made sense based upon what I'd read on the Internet but wasn't sure exactly how to implement it. I followed the instructions I was given (I think) and setup the following:\nI updated the server document so it uses internet sites documents:\n\nI now have an Internet Sites document with the following information:\n\nOn the Configuration tab, here's where I'm enabling HTTP PUT and DELETE.\n\nWhen I open a browser and launch the Sencha Touch app, it renders its UI then connects to the Domino server to request the data using the RESTful agent I've created. Here's the Domino log document for the GET request:\n\nAfter the browser receives the 401 error, it prompts me for the credentials then repeats the request to the Domino server as shown in the following figure:\n\nSo far, expected behavior, right? When I edit a document in the Sencha Touch application, the Sencha Proxy tries to PUT the data back on the server and I get the following error:\n\nSo, last week I thought I was having an authentication problem (since the Authenticated User field in Figure 5 was showing Anonymous). Turns out this was some sort of weird a Safari caching problem, as soon as I switched to Chrome or cleared the cache in safari I was prompted to login and get what you see above.\nSo, looking at this, it looks like I DON'T have the Domino server configured correctly and I could use more of your help. Anyone have any suggestions?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Domino Server 405 Error",
  "date":"Tue Apr 09 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1365552000,
  "url":"/posts/2013/domino-server-405-error/",
  "content":"I'm trying to wrap up an article series for The View on developing Sencha Touch applications for IBM Lotus Domino and ran into a problem that I can't seem to find a solution for – can you help me out? Please?\nI've created a simple competitive information database in Notes and exposed it to mobile devices using several methods. I first built a Rhodes application (https://rhomobile.com) that synchronized data with the Domino server and wrote a series of articles about it. You can see a sample screen shot of the Rhodes application in Figure 1.\n\nNext I did the same thing using Sencha Touch (sencha.com); you can see the application in Figure 2.\n\nAs you can see, I finally got around to populating the application with more interesting content.\nAnyway, as I worked through the Rhodes application, I discovered that by default, the Domino server was blocking HTTP PUT and DELETE requests, so I had to put the following line in the server's notes.ini file:\n\nOnce I did that, the Domino server stopped blocking my requests and everything worked out great.\nYesterday, I was working on the Sencha Touch application and read and create worked great, but as soon as I started editing records in the database I started getting the following error on the server:\n\nI looked in the Domino log and saw that the problematic URL was:\n\nYou can see the complete Domino log entry in Figure 3.\n\nI've searched and searched and can't seem to find the solution to this problem.\nNothing's changed on the server and there's only a few references I can find about that HTTPEnableMethods ini parameter. Most of the stuff I can find on the 405 error all relates to configuring a Domino server to use WebDAV (which I'm not using in this case [am I?]). This was working just fine for my Rhodes application but now fails for the Sencha Touch application and they're both essentially using the same RESTful service.\nCan anyone help me understand more about this problem and hopefully (although hope is not a strategy) fix it?\nIn a side note, I wanted to take a look at the server's notes.ini file and remember that I'd written a utility (back in 1996) called Configuration Manager for Lotus Notes that allowed me to work with a sorted version of the notes.ini . So funny that a utility I wrote 19 years ago is still useful. What fun!\n\nI wonder if I should do an update (the DRCC ini reference link isn't working anymore). You can see the application in Figure 4. I just looked and Wolcott Systems Group has pulled the link to this utility from their web site. No surprise, but sad.\nUpdate Apr 11, 2013\nI'm getting more convinced that I'm not having a Domino server config problem but instead I'm having an authentication problem. Notice in figure 3 that it lists the authenticated user as '-'. I've been poking around in the ACL and have tried setting Anonymous to 'No Access' in order to force a login and even setting Anonymous to Manager - still doesn't allow me to do a PUT to the server.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "PhoneGap Essentials Korean Translation",
  "date":"Sun Mar 24 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1364169600,
  "url":"/posts/2013/phonegap-essentials-korean-translation/",
  "content":"Last week I received a copy of my PhoneGap Essentials which had been translated into Korean (at least I think it's the Korean translation, I can't actually be sure – as I don't read Korean). Here is the book, perhaps you can read it:\n\nAnyway, apparently the book has been licensed for translation into Korean and Traditional Chinese. The Chinese version of the book was supposed to have been published months ago, but I don't know what happened to it. I'll receive a copy as soon as it makes it to my publisher here in the US and of course I'll publish information about the book.\nWhat's interesting about this version of the book is that it's a much better implementation of the book (or at least, the cover). The cover stock is much thicker than the US version , plus it has this pebbled feel to it. Also, the cover extends beyond the width of the book and the extra material is folder over inside the cover, so they have some extra writing there – pretty cool. You can see it here in the following blurry image:\n\nWhat's funny is that the only I can tell that I'm the author of the book is from the inside flap which has my name in English (the front cover version of my name clearly isn't).\nThe pictures of the kids (and now deceased dog) are still in there, so they had fun showing everyone their faces amung all that foreign text.\nIf you have any Korean speaking friends or family who are looking for a book on PhoneGap, mine's the only one (that I know of) that's been translated. Please put in a good word for me and my book!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Coolendar - Not Today",
  "date":"Thu Mar 21 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1363910400,
  "url":"/posts/2013/coolendar-not-today/",
  "content":"I was going to write a bit about a cool calendar site called Coolendar, but apparently it's not working right now. I'll try again later.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Wi-Fi Only Tablets",
  "date":"Tue Mar 12 2013 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1363132800,
  "url":"/posts/2013/wi-fi-only-tablets/",
  "content":"I'm not quite feeling the benefits of a Wi-Fi only device. Having worked for a device manufacturer then a carrier, I guess I'm a bit spoiled when it comes to connectivity. Over the years I've had several tablets, some with cellular connections and some with only Wi-Fi connections.\nI have to admit that I find that the Wi-Fi only devices never seem to have connectivity when I need it the most. At home (of course), at most airports and at many national chains (hotels, restaurants, stores), there's usually access, but like I said – often when I really need it it's just not available.\nI attended the AT&amp;T Dev Summit in January at a hotel in Las Vegas. Being a networking company (although they really don't want to be, they want to be so much more) I expected them to provide Wi-Fi access at the event, and they did, but in the movie theater area where most of the 'sessions' were held, I could get no coverage. I had some research to do between sessions and a desire to catch-up on some emails, but simply couldn't get coverage.\nNow, I was in several movie theaters, away from the conference 'center' but none the less, they'd provided coverage, they should have made sure it was available everywhere. If not, why even bother setting it up and promoting it if it's not most everywhere the conference is being held.\nMy employer provided me with a Wi-Fi only iPad 3 (I refuse to call it the 'New iPad') and I was able to order a Mi-Fi hotspot, but I really don't like carrying (and maintaining charge in) two devices simply to have ubiquitous network coverage. I use the device when I'm at home and at the office, but when I'm out and about I rarely have the Mi-Fi hotspot with me.\nI recently upgraded my Nexus 7 to a cellular version (AT&amp;T) and I'm going to give the old one to my kids. I dropped my Android smartphone coverage and added a tablet data plan and now for $10US a month I can use my tablet anywhere I can use my cell phone. This makes for a much better experience for me.\nThe big issue for me is that I'm a BlackBerry user and I don't have a cellular version of the BlackBerry Playbook. The BlackBerry is awesome for productivity stuff, but when it comes to things like Flipboard, book reading and more – a tablet is still the best option. As long as that's the case, I'm going to have to keep a cellular enabled tablet around.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "More on Email Message Format for Mobile Devices",
  "date":"Sun Mar 03 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1362355200,
  "url":"/posts/2013/more-on-email-message-format-for-mobile-devices/",
  "content":"A few weeks ago I posted an article complaining about how major brands don't consider mobile email clients when they craft their blast email content. I even showed some examples of poor email content design from American Express and RIM.  A reader of the site missed the point of my article and suggested I learn how to use my BlackBerry and enable automatic download of images in the email. Apparently he (or she, not quite sure) skipped reading the article and instead simply saw the screen shots and thought I didn't know what I was doing.\nMy point in the article is that everyone does fancy email blasts with lots of graphics and centered content. That simply doesn't work for mobile devices and I wrote that post in an effort to get people to start thinking about the target audience and adjust their content accordingly. I noticed the other day that the smart folks at Evernote have it figured out, take a look at the email content in the following screen shot:\n\nNotice that it used color and some font treatments, but that doesn't detract from the email message's readability on a small screen (like the BlackBerry used to take the screen shot). That's the way it should be done!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Follow-Up Then",
  "date":"Thu Feb 21 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1361491200,
  "url":"/posts/2013/follow-up-then/",
  "content":"I don't remember how I first learned about this service, but it's pretty cool. Followupthen (https://followupthen.com/) is a free service you can use to remind yourself of stuff. What's cool about it is that you configure reminder settings using the email address you send your message to.\nFirst you have to sign-up for an account. Once you've completed that step, your remaining interaction with the service is all done via email. For example, to remind yourself to pick up a birthday present for your wife in two weeks, you simply send an email message to 2weeks@followupthen.com containing an appropriate subject and optional message body. In two weeks, you'll receive and email with the subject and body of your original email.\nPretty cool!\nThe service supports a wide range of options including minute, hour, day of the week reminders, you can setup recurring reminders and you can setup reminders for a specific date. You can even upload a logo to include in your reminder messages (useful for company use). Premium users can even add attachments to emails to have them sent back to them at the appropriate time.\nYou'll get an email confirmation that the system has recorded your request as shown in the figure below:\n\nAnd, at the appointed time you'll receive another email with the actual reminder message:\n\nNotice that it even allows you to 'snooze' your reminders.\nCheck it out when you get a chance.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Using GeSHi in Joomla",
  "date":"Wed Feb 20 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1361404800,
  "url":"/posts/2013/using-geshi-in-joomla/",
  "content":"If you've been poking around within this site, you may have noticed that I used to post a bunch of source code to the site. I don't write as much code as I used to and much less than I'm accustomed to, but when I setup this site, I found myself posting a bunch of code and wanting to make it render properly on the site's pages.\nBeing new to Joomla!, I poked around a bit and noticed that there was a code highlighting plug-in called GeSHi installed as one of the core plug-ins in any Joomla! implementation. I thought all of my problems were solved, so I started trying to figure out how to make this code highlighter work. A search of the Joomla! documentation proved to me that nobody on the Joomla! project though it was important to document how this plug-in worked. I continued my search and found the GeSHi plug-in's home page at https://qbnz.com/highlighter  As I poked around on the site, I found a bunch of information about how to implement GeSHi within a php-based web site, but nothing that told me how to use the plug-in in my Joomla! site. I quickly gave up on GeSHi and started looking elsewhere.\nIn the Joomla! extension directory, I found another plug-in called Code Citation which seemed to be exactly what I was looking for. It was a standard Joomla! plug-in, so it was installed in no time, and there was actually documentation on how to use it in your Joomla! web sites. I quickly installed it and over the years used it everywhere in this site.\nWhen I upgraded to Joomla! 2.5, I encountered problems with Code Citation but eventually worked through them and got the site up and running. The developer's stopped work on the project and it isn't compatible with anything newer than Joomla! 1.6; I wrote about that experience here #######. Last week I noticed that my BlackBerry Development Fundamentals web site was running on a discontinued version of Joomla! and I needed to upgrade it. As I upgraded it, I noticed that I had some source code on the site, so I had to install Code Citation on this upgraded site.\nEven though I was able to get it working on this site, something was different about the BlackBerry Development Fundamentals site, and the plug-in wouldn't work there. Every time I got close to a page that used Code Citation, the server would deliver a blank page.  I'd pestered the developer of the plug-in so much when I was trying to get Code Citation working on this site, that I didn't feel right bugging him again. Besides, I really wanted to figure out the GeSHi plug-in anyway, so I set about finally buckling down and figuring it out.\nFirst, I found this site: https://bitsensei.com/web/joomla/9-using-geshi-in-joomla/ which explained how the default Joomla! implementation of GeSHi didn't include all of the supported language plug-ins (Joomla! only includes a few of the many included with the default GeSHi installation) and how to update the site to include all languages. Additionally, it mentioned how to invoke the plug-in within your web site, but not how to actually implement that on your site's pages. Ugh! So close.\nNext, I found the following site:  https://dotcomxl.com/index.php/tutorials/web-design/115-joomla-syntax-highlighter which finally had the information I needed to make this work. The article first provided all sorts of information about how to enhance the output of GeSHI then finally at the end of the article I saw this:\nNow that the plugin is enabled, if you want to show code in your articles you should switch to HTML view in your WYSIWYG editor and use this format:\n\nThat's exactly what I'd been searching for – the other sites mentioned the pre tag, but not how you inserted the code into your article. When using Code Citation, the Code Citation processing tags go at the beginning and end of your code – you don't need to switch to the HTML editor to enable it. GeSHi apparently requires that, but it wasn't described that way in all of the sites I looked to for help.\nSo, now I finally knew how to enable GeSHi in a Joomla! web site. Simply bracket the code you want highlighted with the pre and /pre tags, but do it within the HTML editor as shown in the following figure:\n\nOf course, going back to the GeSHi web site, I see now that the documentation describe the pre tags but doesn't mention that you have to insert them from the HTML editor. Another perfect example of how many developers write documentation from the standpoint that you already know how to do something instead of writing it from the standpoint of someone who DOESN'T know how to do something.\nIt…works – the BlackBerry Development Fundamentals site's code samples render like they should, but I like Code Citation much better. I wish the developer of the plug-in would continue to work on it and update it for Joomla! 2.5 or even 3.0. It's a much simpler solution and doesn't require you to go into the HTML editor to format some source code. Right now this site is still working, so I won't have to revisit this topic until a Joomla! upgrade b",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Using jUpgrade",
  "date":"Sat Feb 16 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1361059200,
  "url":"/posts/2013/using-jupgrade/",
  "content":"I've upgraded a few sites lately from Joomla! 1.5 to Joomla! 2.5 using jUpgrade. The upgrade from 1.5 to 2.5 isn't exactly an upgrade, it's more of a migration, so you really have to use tools like jUpgrade to make it work.\nJUpgrade installs as a Joomla! Component and adds its own options to the Joomla! Components  menu. It essentially downloads a version of Joomla! 2.5, installs it in a sub-folder from your original Joomla! 1.5 installation then copies 'all' of your stuff to the new site. At the end of the rather quick and painless process, you have two copies of your Joomla! site; one in the site's original location and another in a sub-folder called 'jupgrade'. You maintain access to your original site, but have this new version to work with to test to make sure everything migrated OK (it didn't, trust me) and to upgrade your template, extensions and so on. Chances are your Joomla! 1.5 template won't be compatible with Joomla! 2.5, so no matter what, you'll have to acquire, install and configure an updated template in your upgraded (migrated) web site.\nYou may have noticed that I said above that everything won't migrate correctly – that wasn't a complaint, simply a statement of the truth. jUpgrade is amazing considering what it does and how much it costs (it's free). Unfortunately, there's so many plug-ins, components and modules available for Joomla! that there's no way for any migration tool to be able to accommodate everything which might be running in your site.\nThe developer(s) of jUpgrade have done what they can to accommodate the most popular options, but after the conclusion of the jUpgrade migration, you'll have all of your articles, categories and menus copied over into the new site, but not much else. When you go into the new version of the site, you'll have to start adding back your extensions and putting everything back where it belongs. It's a challenging task, but I found it to be a fun process. It forces you a chance to rethink your site's structure, layout and configuration – and ultimately my 'new' sites look nothing like my original sites when I'm done.\nWhat Didn't Work\nHaving migrated three sites, I thought I'd fill you in on some of the things that simply did not migrate properly using jUpgrade.\nCategories\nThe first thing I noticed was that Joomla! article categories got copied over to the new site, but didn't work correctly. In some cases, I had to go in and edit then save each category before things would work correctly. In other cases I found that my top level categories were setup as sub-categories to the Uncategorized category. Either way, expect that you're going to have to do some work on your categories before you can go live with your migrated site.\nNewsfeeds\nI also noticed that on several of my migrated sites, any Newsflash Module settings don't make it across correctly. In several of my sites, I had a newsflash module rendering a random article on part of the site. After the migration, that module was still there, but was configured to show many articles in a particular order – rather than the one article with random as I originally had it setup.\nSH404SEF\nI use the SH404SEF SEO, analytics and security module from Anything Digital on several of my sites. I noticed that during the jUpgrade migration process, something goes wrong and SH404SEF stops working correctly. For this site, I've not been able to resolve the issues I have – even with support from Anything Digital. If you look at links on this site, you'll notice that I have the external link symbol appearing to let you, my readers, know when I'm sending you somewhere else. It's a feature of the SH404SEF component and I like it. If you look at some of the articles that precede this one on the site, you'll notice that some links (but not all) that point to external sites have the symbol but not others. I can't figure it out nor can I fix it.\nRecommendation is to completely uninstall SH404SEF before starting the migration, and then reinstall it later. I'm not sure it that will help, but it's worth a try.\nGoing Live\nAfter you've completed the migration process and made sure everything is working well on your new site, migrating from the old site to the new one is quite painless. Simply delete the old site's files (I download them first, then copy them to another folder on my server – can't have too many copies) then copy the files from the jupgrade folder to the original site's folder. With that done, you're all set – just be sure to test everything before you decide you're done.\nAfter you've made sure everything is working OK, go into your MySQL manager and open your site's database – you'll find two sets of tables there, your original Joomla! tables plus a new set created by jUpgrade. It's not required, but you will want to remove (drop) the original tables when you're sure the new site's working as expected.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Ignoring Mobile Email clients",
  "date":"Fri Feb 08 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1360368000,
  "url":"/posts/2013/ignoring-mobile-email-clients/",
  "content":"I've always been surprised at how major brands and larger organizations ignore smartphone users in their email blasts. I'm an American Express customer and get email promotions from them on a regular basis. When I open one of their messages, I see something similar to the screen shot shown below.\n\nEveryone seems to think that you have to have lots of color and everything centered in an email blast, but at the end of the day that simply doesn't work for mobile users – and I have to imagine that many if not most users read these types of emails on their mobile phones exclusively.\nI need to do some testing on this, but since the email is in HTML format, can't it do some work to understand the viewport it's displaying in and adjust accordingly? Mobile users should not have to scroll past a bunch of junk to get to the content and the content should never be centered like it is in the screen shot. That email is useless to me and I simply can't read it on my mobile device without scrolling around to view the content. If I'm reading on mobile, I should see all of the content flush left with natural wrapping.\nIn my mind, BlackBerry was the worst offender – take a look at the following screen shot. This was taken a while ago, but it was an email to BlackBerry users, with specific instructions that the message would look best on a desktop computer. At least they moved the content to the left margin so the email is at least readable on a mobile device.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Carrier APIs",
  "date":"Wed Feb 06 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1360195200,
  "url":"/posts/2013/carrier-apis/",
  "content":"I have to admit that I simply don't get Carrier-specific APIs. I used to work for RIM (now called BlackBerry), working with their largest carrier and later on worked at that same carrier. I know how desperately the wireless carriers don't want to simply be a pipe (provide me with network access) – but instead want have all sorts of value-add products they can sell you. At the end of the day, all I want them to be is a pipe and I'd gladly pay them more money per month if they'd simply give me a wireless network connection for my devices and let me use them any way that I want to.\nI know it costs a lot of money to create and maintain the wireless networks, and I know that some users use more bandwidth than others (iOS users vs. BlackBerry users for example), so just go ahead and charge me based upon how I use your network.\nAnyway, I was at the AT&amp;T Dev Summit last month and saw some interesting things there. AT&amp;T has been working with Sencha and others to create a suite of APIs that mobile app developers can use in their applications. There's some pretty interesting location based services (LBS) APIs available, plus services around SMS, billing and so on that could be pretty useful for mobile developers.\nThe problem is that these APIs are available from a specific carrier (the LBS APIs are a global product, available for most carrier's devices, but in this case AT&amp;T has their own 'branded' version of the service). If I'm building a mobile application, I don't benefit from leveraging APIs that are usable for only a subset of my available customers. If I'm going to build functionality in my application, I have to be able to use it over all customer devices – having to implement a different system depending on which carrier a customer is on is inefficient and too expensive to implement for many smaller development shops.\nIn the Dev Summit keynote, one of AT&amp;T's partners demonstrated an application which allowed an application to type in their phone number then the application retrieved the mobile user's account information from the carrier.  If you know all of your customers are on AT&amp;T, then the API is useful, but I expect that the number of cases where that is true is…zero. That makes that particular API pretty much useless. On top of that, the demo included the user typing in their phone number, why? They were showing a native application running on the iPhone; native applications know (with the appropriate permissions of course) what the device's phone number is. How are you helping me if I need to type in my phone number before you retrieve my account information from the carrier?\nUse the local API to determine the device's phone number then populate the rest of the form with the data from the carrier. I imagine they did it that way to demonstrate that all that was needed was the phone number in order to populate the entire form, but it was a silly demo.\nWhat's needed is a common, cross-device, cross-carrier on device app and API that allows a user to define common information about themselves (name, address, phone number, credit cards) then make it available to any application that asks for it (with the appropriate approval of the user of course). Then, when I get the device, I enter in all of that information once then any app I authorize can access that information. If I don't authorize it, there is no reason the local API couldn't simply prompt the user for authorization when needed. That would be a much easier system for mobile developers to implement and much less work for the mobile user. Everyone wins and there's no need for cloud-based, carrier-specific APIs.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Too Many Eclipse Instances",
  "date":"Sun Feb 03 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1359936000,
  "url":"/posts/2013/too-many-eclipse-instances/",
  "content":"I've been doing some more mobile development lately – building some applications on the SAP Mobile platform (what was formerly known as the Sybase Unwired Platform) and therefore cranking up some development environments for Android, BlackBerry and even iOS. In preparation for this work, I was updating my Eclipse instance on my Mac Mini plus creating a new Windows VM with Eclipse and all of the tools I needed. One of the things I noticed is that the whole concept of Eclipse plug-ins is essentially broken when it comes to mobile development.\nLet me explain…\nThe Android development tools embraced Eclipse early on and worked very hard to make sure their stuff simply ran on most any version of Eclipse out there. There were some initial incompatibilities with the Java 7 SDK, but that's to be expected with a big version upgrade for an underlying technology like Java, and although the Android SDK installer wanted to install its files in the Windows Program Files folder, that rarely worked. At the end of the day though, the Android SDK fit nicely into most any version of Eclipse.\nI just downloaded the latest version of the Android SDK and noticed that the installer was gone (not sure I'm really a fan of that) and there was a new folder included in the download with a complete instance of Eclipse. OK, so Google's now telling us that they suggest that you do your Android development with their instance of the Eclipse IDE.\nThe BlackBerry Java SDK is fickle, very fickle. Even though the Android DSK has embraced most any version of Eclipse, with the BlackBerry Java SDK, it supports only Eclipse version 3.7 (https://developer.blackberry.com/java/download/requirements/). That wouldn't be that bad, except that 3.7 is pretty old. So, imagine you're using the latest and greatest Eclipse stuff to do Android or some other development, you're going to have to maintain a completely separate, older version of Eclipse simply for BlackBerry development.\nHere's some screen shots of what you get when you successfully install then try to run the BlackBerry Java development SDK in a current version of Eclipse.\n\n\n\n\nWhat was particularly maddening about this particular problem was that the error messages about the pre-processor configuration are cyclical, the one message appears, then you're prompted to restart Eclipse then the error message appears, then you're prompted to restart Eclipse. It never ends.\nNotice too the error messages about missing a DLL? Unfortunately, that error was generated on a Macintosh – not sure there's a lot of DLLs on a Mac.\nThe IBM Worklight developer tools have similar restrictions – I downloaded the trial last year and was having fits trying to get it to work. I expect everything to be like the Android tools – simply work in most any version of Eclipse, but after struggling with the Worklight plug-in installation, I finally looked at the system requirements and noticed it too only supported an older version of Eclipse.\nThe SAP Mobile Platform (SMP) tooling uses Eclipse 3.7, so it's really easy to setup BlackBerry and Android Java development environments within the SMP development tools. At the end of the day though, you're still setting up a separate environment just for SMP development – and adding yet another Android instance to your configuration if you want to do both Android and BlackBerry development in the same IDE where you're doing your SMP development. I would be happier though if SMP was a plug-in as well, rather than a complete IDE installation like it is today.\nThe moral of the story is that it simply shouldn't be this hard! Google's making the investment to make their stuff work in most any version of Eclipse – how hard can that be? RIM (now called BlackBerry) and IBM I imagine have to have similar sized development teams, why can't they build Eclipse plug-ins that just work? Granted BlackBerry has been really busy with BlackBerry 10, and has essentially abandoned Java development, you'd think they would want to make things simple for their developer community.\nWith so many of the mobile development vendors supporting restricted versions of Eclipse, developers can't truly benefit from the plug-in capabilities of Eclipse. Either Eclipse has made making compatible plug-ins too hard or these mobile development tool vendors or the vendors are simply not trying hard enough. I've never built an Eclipse plug-in, so I really can't say. At the end of the day though, what's the value of an IDE with a plug-in architecture if I still have to install and maintain separate instances of the IDE just to use different plug-ins?\nIf you're not going to do that – at least make the system requirements more visible so that people like me who don't go looking for the system requirement before installing an Eclipse plug-in can know that what they're trying to do won't work. Why not include the supported eclipse version in the plug-in name?\nBetter yet, why not simply include version checking into the plug-in installat",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "The Value of AppOS integration to an Enterprise",
  "date":"Thu Jan 31 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1359676800,
  "url":"/posts/2013/the-value-of-appos-integration-to-an-enterprise/",
  "content":"Note: this is a copy of an article I posted to my SAP Community Network (SCN) blog at https://scn.sap.com/blogs/johnwargo.\nI mentioned in my previous post, it seems that a lot of organizations are thinking more lately about tablet development than smartphone development. Many customers have also told us that they're looking seriously at Windows 8; that got me thinking about what makes Windows 8 interesting to those organizations. Now, many of you immediately started thinking about the enterprise features of Windows 8 such as the ones described in Eric Lai's post on the subject (https://zdnet.com/in-the-enterprise-windows-8-tablets-may-zoom-past-pcs-7000006456). On the other hand, I'm a developer, so I immediately started thinking of the value Windows 8 tablets had in the enterprise and that got me thinking about how well applications can interact with the device OS (whether it be smartphones or tablets) and what that means to enterprise users. Of course, SAP has already announced six enterprise applications for Windows 8 – you can read more information about those apps here: https://zdnet.com/sap-to-offer-six-enterprise-enhanced-windows-8-apps-7000007310/\nIt seems to me that one of the ways an organization increases the benefit of a mobile device is through the ways it exposes important business data to the mobile user and the ways that the mobile user can interact with the data.\nThe market has already shown us that the iOS device is mighty popular with enterprises and Apple, through its periodic updates to the OS, has been adding features for the enterprise over time. They've still got a while to go to catch up with the enterprise features of the BlackBerry platform, but the value is definitely there. iOS device users have their mail, calendar, and (finally) tasks on their device, plus the personal and any enterprise applications they need. What the OS doesn't have though is app to app or app to OS integration that could make the device more useful to enterprise users. Apple has (for security and performance reasons I imagine) deliberately restricted how an application can interact with other apps on the device and there's very little (if any) visible integration with the device OS. iOS applications can pass data to other applications, but seamless integration is…limited.\nFrom early on, the Android OS has supported widgets, which allow a developer to create an application that renders data directly on the device's home screen. We have seen examples of this in the weather widget found on any Android phone or the Facebook widget that shows the latest entries on a user's timeline. For the enterprise user, there's real value in using this concept to render enterprise data as well. Imagine an enterprise sales application that exposes a portion of the application's UI as a widget; the widget could change the background color and/or the content rendered within the widget's UI depending on user-specified criteria. When certain customers report critical issues, change the background to yellow (or red as appropriate) and list the customer names or project names for example, allowing the user to immediately understand the status of the customer(s) without even opening the app. The user unlocks the device and can immediately see what's going on – clicking on the widget to open the app and viewing the details.\nThe BlackBerry platform has had something like this for many years – using the push capabilities of the BlackBerry Enterprise Server (BES) or even the PushMarks service for BlackBerry Internet Service (BIS) a back-end application can send data to a mobile application running on the BlackBerry and change the application's icon to indicate some sort of status. Developers would build apps that changed the icon color to indicate status (yellow for warning, or red for critical for example) or even add some sort of numerical indicator to the icon. The user looks at the device screen and immediately knows that something needs their attention.\nBlackBerry 10 is supposed to make inter-app integration mainstream through its BlackBerry Hub as described in Paul Mah's recent article (https://zdnet.com/blackberry-10-is-about-integration-usability-7000008202/). I'm still waiting for a chance to play with this feature, but with RIM's multi-threaded OS (where unlike iOS, apps are encouraged to work in the background) and the Hub, the user simply swipes to see the notifications area and all of the things that require his or her attention are listed there. It will be easy then for an enterprise application to notify the user any time critical data is available – right in the place where the user will already be going to for email, calendar notices and more. Knowing the BlackBerry developer community like I do, I'm sure a lot of developers, especially enterprise developers, are going to make good use of this integration.\nOn Android, the widget is the app – what you create is the application UI and the OS allows you to display the app",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Switching Development from Smartphones to Tablets",
  "date":"Thu Jan 31 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1359676800,
  "url":"/posts/2013/switching-development-from-smartphones-to-tablets/",
  "content":"Note: this is a copy of an article I posted to my SAP Community Network (SCN) blog at https://scn.sap.com/blogs/johnwargo.\nMany years ago, one of the struggles enterprise-focused mobile device manufacturers, wireless carriers and mobile development tool vendors faced was getting companies to make an investment in building mobile applications for their employees. As we all know, with the introduction of the iPhone and Android plus the effectiveness of the “There's an app for that” campaign, it's become less of an issue. BYOD has put a business-connected smartphone in a lot of hands and organizations have built many mobile apps in order to create efficiencies for that mobile workforce.\nIn some recent conversations with customers though, I've learned that many organizations are building fewer smartphone apps and more tablet apps for their mobile users. That revelation didn't really surprise me, but I didn't expect we'd get to this point so quickly. I think however that several factors are affecting this trend:\n\nBuilding for tablets allows organizations to focus on a reduced number of mobile devices (and configurations) to support. The folks at RIM got hammered for a long time because developers had to support so many different form factors/screen resolutions over the years. The same thing has been affecting Android developers for a long time and of course is now affecting iOS developers as well, although not as much. There's still a lot of variance in tablet form factors, but with the larger available work area (discussed in the next point) developers simply don't have to work as hard to create a compelling and useful UI for their applications.\nThe larger work area available on tablets allows an organization to fit much more information on the screen, which will ultimately help users of these applications be more effective with the application and be able to work with much more data at the same time. With the way the human brain works, when doing analysis of sales data or other important business information, being able to see as much data as possible at once makes it easier to 'work' with the data.\nThe way a user interacts with a tablet application vs. the same smartphone application is different – there are operational efficiencies inherent in tablet applications simply because of the amount of information that can be displayed on the screen at one time. Reducing the number of touches and swipes a user has to perform to access all of the information they need to make a business decision has to make tablet applications 'easier' to use.\nDevelopers of tablet applications have potentially more flexibility in their UI designs. For some reason, there seems to be less of a requirement that tablet applications look like other applications running on the device. With smartphone apps, and developers bound by Apple's Human Interface Guidelines (HIG - https://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/Introduction/Introduction.html), there is a propensity for apps to all work in a similar way. Developers building many of the tablet applications that I've worked with don't seem to be encumbered by that particular restriction.\n\nThe thing about tablets vs. smartphones is that on top of everything else they do, tablets seem to be more of a presentation tool than smartphones. What this means then is that organizations that provide tablets should:\n\nEquip their employees with tablets with greater memory capacity. I'd always had 16GB tablets until I joined SAP and found myself with a 32GB tablet in my hand. SAP enables its employees with a lot of mobile apps (mostly tablet apps), but at the same time provides tools which allow me to maintain a repository of my important documents on my device (see the following point) – which quickly consumes that extra memory.\nBuild a mechanism which allows employees to easily load employee specific documents and files on the tablet. This includes custom sales presentations, customer background information and more.\nBuild a mechanism which allows IT to easily distribute important sales and training materials onto employee devices.\n\nThis becomes very important with sales-focused positions – where every sales person for example needs to have the latest and greatest product videos available at all times to show to customers.\nIn my opinion, mobile operating systems need to allow for deeper integration between applications and the device OS – but that's a topic we'll discuss in my next post. Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "DMCA Big Brother",
  "date":"Sun Jan 27 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1359331200,
  "url":"/posts/2013/dmca-big-brother/",
  "content":"OK, let me see if I got this straight:\nI have a legal right to make one archival copy of copyrighted material I own, say for example to make a copy of a music CD so that if something happens to the original, I can still listen to the music, but if the disc has copyright protection, it's illegal (through the Digital Millennium Copyright Act (DMCA)) to break the copy protection in order to make that copy.\nIf that wasn't stupid enough, now it's illegal to jailbreak my smartphone? https://theatlantic.com/business/archive/2013/01/the-most-ridiculous-law-of-2013-so-far-it-is-now-a-crime-to-unlock-your-smartphone/272552/\nImagine that I purchased an iPhone – I paid for it and I own it, and I want to install software on it that Apple doesn't want me to install on it. Mind you, this isn't software I shouldn't install on it, or illegal software, but quite simply software that Apple has decided that they don't want me installing on it. Apple's telling me what I can and cannot do with this device – even after I've paid them their full price for the device. In order to be able to do what I want to do with this device, things that are not illegal, simply something I want to do with the device, the federal government has made it illegal to complete the process that allows me to use the device as I see fit.\nDoes this make any sense people?\nCan you give me any other examples of situations where you buy something from a vendor and are not allowed to use it the way you want? Can you imagine GM selling you a car, but telling you that you can't drive the car on any road you want? That the government would make it illegal for you, even after you've paid full price for the car, to remove whatever restriction GM has put in place to keep you off certain roads?\nYou've simply got to be kidding me. Make it stop people, please make it stop\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Discovering Raspberry Pi",
  "date":"Sat Jan 26 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1359244800,
  "url":"/posts/2013/discovering-raspberry-pi/",
  "content":"Many months ago I learned about the Raspberry Pi hobbyist computer. Apparently it was created to provide an inexpensive system that kids could use to learn programming. At $35US it really hits the mark.\nI understand their goals well; I had access to micro computers in High School back in the late 70's, at home at about the same time and in college as well. The reason I'm a computer developer is because I was able to be one so early in life and it definitely stuck. My first computer was a Ti Ti-99-4a and the second was a tricked out Apple //e that I kept for many, many years. I spent a ton of time writing code for those boxes and that quite possibly have something to do with why it took me so long to get married. That's a story for another time.\nAnyway, I was excited about the potential for the Pi, so I ordered one and it sat in a box for a while. My 9 year old son and I got a chance to hook it up yesterday afternoon and had a blast. If you haven't seen one before, here's a picture.\n\nEssentially it's a mini-PC with an ARM processor, HDMI port, Ethernet Port, two USB ports and some more stuff. It runs on a cell phone charger (I'm using a BlackBerry charger in the photo). You burn a special version of Linux to an appropriately sized (2GB minimum) SD card, plug everything in and you're ready to go.\nWhen it fires up,  you get the standard linux command prompt and can interact with the device through the command prompt or you can start an X-Windows UI environment. The default Raspberry Pi Linux image (Raspbian – a Raspberry Pi version of Debian) has a bunch of software included, including some Integrated Development Environments (IDE) for Python (the Pi in the Raspberry Pi name) and Scratch (a drag and drop development environment for kids).\nI'm not going to go into all of the details here, there's some good books on the subject (I've read two) and a bunch of information available online. It's really easy to setup and to use. Knowing a little bit about Linux makes it a little easier, but not much. My son and I fired up the Scratch IDE and using an example from the O'Reilly book on the subject created an alien shooter game in an hour and had a blast doing so. My son's learning a little bit about computer programming, we've already added some enhancements to game and have more planned. Here's a picture of my son working on the latest version of his game.\n\nI ordered a few 8 GB SD cards yesterday. I'm going to set one up for my daughter so she can work with Scratch in her own environment. I have a 32 GB card I'm going to use as my personal playground – along with the default debian distro, there are Fedora and other Linux distributions available for the Pi, so I'm going to give them a try.\nThere's also a XBMC Media Center distro for the Pi (https://wiki.xbmc.org/index.php?title=Raspberry_Pi) that I'm going to download and play with. I'm a HUGE fan of the Sonos players, but I'm going to see if I can setup the Pi in my living room and pull my (legally obtained) music from my Windows server.  I'll probably write about that here later.\nNext on my list of things to play with is the Arduino, an open source, programmable microcontroller. I'm not much of an electronics guy, but I truly want to be one. I imagine a programmed microcontroller in a pumpkin sitting on my front porch at Halloween.  Also, my son and I have some interesting ideas about what we want to do with his Pinewood Derby car next year.\nA neighbor geek like me recently told me about the TI MSP430 micro controllers that compete with the Arduino device. At less than $5 per device I've ordered some of them and I'm going to play around with them (with my son of course) when they get here.\nWhat this means, of course, is that I now have more to write about here. What fun!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Raspberry Pi"
  
  ]
  },

  {
  "title": "Take two tablets and call me in 2015",
  "date":"Thu Jan 24 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1359072000,
  "url":"/posts/2013/take-two-tablets-and-call-me-in-2015/",
  "content":"Editors Note: The following is the first guest post published to this site. David Via is a long time friend (a really, really long time) and a really smart guy. Enjoy!\nBy David Via\nI was conducting a ride along activity today when I was struck by a remarkable idea.  Could it some day soon make sense for some mobile professionals to carry two tablet devices?\nLet me backtrack just a bit.  A ride along is when I shadow a mobile employee of a large enterprise in his daily activities to help identify ways in which they might realize benefit from mobile applications.  Today I was riding along with a sales person.  In case you have been living under a rock for the past two years, sales people absolutely LOVE mobile tablets.  I have heard tablets (OK, specifically the iPad) referred to as &quot;the greatest sales tool ever invented&quot;.  Tablets are an ideal platform for mobile sales professionals. They are small, light and fast. They encourage interaction and collaboration with a customer over an intimate on screen experience.  Quite the opposite experience of opening up a notebook computer in a customer meeting in which the flipping open of the screen essentially creates a &quot;wall&quot; between the seller and the his prospect.  Tablets are equally terrific for presenting content and quickly capturing information on the fly.\nAnd therein lies the problem.\nWhile I was observing the sales interactions on my ride along today, I found myself in a dilemma.  Where would mobile applications on a tablet have the greatest impact?  Facing the customer or facing the seller?  Certainly both have a lot of value.  A highly interactive presentation - think 3D walkthroughs or detailed product models -  on a tablet could augment the sellers' knowledge and presentation.  At the same time a true sales force enablemment tool on a tablet - here a guided selling tool comes to mind, or other job aid that truly supports the seller, not the type of management-driven data gathering that traditional CRM or SFA tools sometimes turns out to be - would really help the sales person to perform better in their day to day role.\nBut we only have one tablet, right?  So maybe we just need to get another tablet.\nIt sounds crazy at first, but is it?  I have run into this dilemma myself in my role as a frequent presenter.  I'm often asked why I present slides from my Macbook and not from my iPad.  The simple answer is that I rely on my iPad to take notes and there's really no way to use one tablet screen to do both.\nPrices are falling and so are device sizes and weights.  Even in today's market two tablets cost and weigh less than the tablet and notebook combo that many of us travel with to customer meetings.\nSo maybe the ideal technology travel combo of 2015 will be two tablet devices and zero notebook computers?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Guests"
  
  ]
  },

  {
  "title": "Updated Site",
  "date":"Wed Jan 23 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1358985600,
  "url":"/posts/2013/updated-site/",
  "content":"Well, I finally did it – I completed the site's upgrade from Joomla! 1.5 to 2.5. I started the project back in August and I haven't been working on the project the whole time. I just ran into a couple of small, nagging issues and stepped away from it for a while as I worked on other things (like my day job). Of course, Joomla! 3.0 came out in the meantime, so I have to make plans to do that upgrade soon (as 3.0 is way, way cool and implements some features I really want to use on the site).\nI used a Joomla! extension called JUpgrade to manage the upgrade process. You install it on your site and execute the process and it creates a new folder (under the current site's folder) and a new set of database tables (with new table prefix) then migrates all of your 1.5 data into the 2.5 format. It is really slick and works really well – especially for a free piece of software created and (I think) maintained by one guy.\nAt the conclusion of the migration, I had two sites – the old one and a relatively stable new one. The next task was to go through EVERYTHING in the new site and make sure it worked. JUpgrade only supports a subset of the Joomla! extensions I was using, so I found an awful lot of places where I had to install an updated version of an extension (I couldn't in some cases install the upgrade before migrating, because the new version might not be compatible with the old site). I should have gone through and updated everything first, but I think (can't remember now) I forgot to do that.\nAnyways, I poked and prodded at this thing and finally got almost everything back up and running in a few hours. It was fun and exhilarating work, I don't know what it was about the task, but I really, really enjoyed it. I guess the prospect of taking a completely new look at the site and its functionality (it's been up for almost 4 years now) was fun.\nThe 'old' site (it was live just a day ago and now it's old?) used a template from Joomlashack called Weblogic and it was cool in the fact that it used the entire width of the page (which modern Joomla Templates, until very recently, did not do) and because of that I had components on the left and right of the page with content in the middle. As I started this project, none of the Joomla! 2.5 compatible templates I could find supported that. So, I set out to find a new template and selected Simple Tech (also from JoomlaShack); it's really cool and I love orange. I hired a local design firm to make the logo and I was all set.\nSince then of course, Joomla! templates have now gone 'responsive' and can again make use of most of a page's width. I'm waiting for the folks at JoomlaShack to upgrade Simple Tech to use the responsive layout, but for now you (and I) are stuck with the 960 layout popular these last few years (ugh).\nSo, what held me back? Getting CodeCitation to work. When I first built the site, I quickly found myself needing to be able to highlight application source code in a neat way on the site. I found that the Joomla! project team had implemented a syntax highlighter called GeSHi – but I couldn't find information about how to use it ANYWHERE. Even the GeSHi site only shows you how to implement GeSHi, not use it. So, I went searching and found a plug-in called CodeCitation that was free, worked and was documented at least well enough that I could get started. So, after the upgrade, I went looking for an updated version of the CodeCitation  plug-in and couldn't find one. The last version was only compatible with Joomla! 1.6. I installed that version and quickly learned that I still had the same problem. When you loaded pages that had source code highlighted, you'd get an error when the page loaded. I located the plug-in's author and emailed him – he was kind enough to respond, but was 'planning' on updating the plug-in but had no timeline in mind. Crikey.\nI thought about switching to the built-in GsSHi, which was now better documented – I at least knew better how to use it, but that would take a lot of work. The CodeCitation developer was responsive, but didn't have a lot to say – clearly he's moved on to other things.\nSo, I put everything down and stepped away for a while. Of course, life happens and holidays too, so it was not until a couple of days ago that I picked it back up again (about 5months later). I started really looking at the content, trying to figure out why the plug-in was failing. I quickly learned that only some of the pages were generating errors, the plug-in worked on some articles, but not all. Of course, then I started looking at the differences between the articles that worked and the ones that didn't – and found the problem. It was my fault all along!\nCodeCitation uses some markup you add to your content to identify the areas that you want it to manipulate. In that markup, you add a class element and identify the brush you want to use (language) to markup the content as shown below.\n\nIn this example, the brush is set to vb (for Visual Basic).",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "iOS Calendar Problems",
  "date":"Wed Jan 23 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1358985600,
  "url":"/posts/2013/ios-calendar-problems/",
  "content":"I was supposed to be on a conference call a while back with a colleague who never showed up. He emailed later asking about the time of the call and I couldn't figure out why there was confusion – a calendar entry is a calendar entry, right? As long as he accepted the meeting invite, it should be on his calendar, right? Wrong.\nOf course, those of you who work in Mobile are already thinking you know what happened. He was looking at his calendar on a mobile device and was in a different time zone than the meeting and the mobile device didn't update accordingly. Well, you're partially right – he was on a mobile device, but the device OS actually transpired against him. The calendar entry was on his calendar and his mobile device knew which time zone he was in – what happened was that the device actually ignored all of the information it had and deliberately showed the appointment on his calendar at the wrong time.\nI was in Madrid a while back (at the SAP SAPPHIRE NOW! &amp; TechEd conferences) and was trying to figure out where I was supposed to be. As I looked at my iPad calendar, I saw something similar to what is shown in Figure 1. If you look at the top of the image, you'll notice that it clearly states that it's 11:03 AM. Looking at the image, on the right side of the calendar, you'll notice a red circle and line indicating what time on the calendar I'm working with. Notice the discrepancy? Even though the device knows it's 11:03 AM, it is forcing the calendar to highlight a completely different time. \nYeah, that's a feature I want on my mobile device.\n\nPlease don't even get me started on why there are duplicate entries on the calendar – my BlackBerry doesn't do this, but my iPad does. Ugh.\nAnyway, I suddenly understood why my colleague missed the meeting. He was in a different time zone and his device was telling him that the meeting was at a different time than it actually was.\nI poked around at this for a while and I finally found the answer. For some bizarre reason, Apple iOS doesn't show appointments on your calendar at the correct time unless you change one of the settings on the device. Take a look at Figure 2, it shows Calendar settings under the General tab, notice the setting labeled 'Time Zone Support'? Well, when you turn that setting off, the device shows appointments using the current time zone set on the device.\n\nThis isn't something I think should be configurable, but apparently Apple does. When I switch time zones, my BlackBerry simply detects it for me automatically then displays all appointments  in the current time zone – which is exactly how it should work.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "PHP Application Installation Problems",
  "date":"Sun Jan 20 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1358726400,
  "url":"/posts/2013/php-application-installation-problems/",
  "content":"I'm a big fan of open source content management systems (CMS) and I've built several web sites using Joomla!, Drupal and Concrete5 plus I experiment with many others. I'm also a huge fan of FatCow and recommend them to anyone who is looking for a great hosting provider.\nWith all of my experience with these tools, I was really frustrated a while back when I stopped being able to install many of these tools in my hosting account. My existing application installations worked great, I simply couldn't install anything new. I would create a SQL database on my server, FTP the application's files to a folder on the server then start the installation process only to have it fail. For the Joomla! 2.5 install for example, it would get to a page during the installation process and simply hang.  I looked in the server's error logs and really couldn't find specifics about what was going wrong.\nWell, I think I finally found the problem.\nFatCow had upgraded to PHP 5.3 a while back and I switched my server over to the new version. These applications I was installing were making use of PHP sessions and in my hosting provider's PHP setup they incorrectly configured the environment. PHP uses a configuration setting called session.save_path to specify the location where the PHP server should place its session data for each user. By default, the variable is configured like this:\n\nbut on my server, that folder was not accessible by me (or apparently the PHP server). So, to fix the problem, I modified the PHP server's configuration file and pointed the variable to a folder I did have access to (I created a new folder called php_sessions off my server's root). I ended up with something like the following:\n\nOnce I did that, all of a sudden everything started to work.\nI think perhaps my hosting provider had created a php_sessions folder for my account some time back and I'd deleted it not knowing what it was (something I know you should never do on a server, but sometimes I can't help myself). But with this fix in place everything's good again.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Big Brother",
  "date":"Thu Jan 17 2013 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1358467200,
  "url":"/posts/2013/big-brother/",
  "content":"I was reading an article recently on Popular Science about an algorithm that can stitch together mobile phone video footage of the same event into a single, synchronized, multi-angle film. Here's the description from the article:\n&quot;As we upload more and more videos to the Internet—one hour of new video every second to YouTube alone—experts are finding new ways to mine them. A team led by Igor Curcio of Nokia's Research Center, for example, has developed an algorithm that stitches concertgoers' cellphone footage into a single, synchronized multi-angle film. The concept is relatively simple: the audio track serves as a guide to sync up the footage, and the software chooses the best shots. Curcio has no real business model yet—photography is prohibited at most concerts—but giving people the ability to identify and coherently connect common elements in multiple videos is nonetheless a step toward something significant.&quot;\nAs I read this article, I thought it was pretty cool. I don't imagine it's a very complicated algorithm, assuming that you know the videos are all from the same location (many photos and videos have timestamp and even potentially longitude and latitude information stored with the file), aligning the video streams along the sound track then selecting (whether manually or automatically) the 'best' image/angle to use for a particular time slice shouldn't be that hard. I imagine that with this technology we'll start to see some VERY interesting videos produced from all sorts of crowd events.\nI saw an automobile commercial a while back where the manufacturer had hundreds of folks line up along a car's route and film the car with their smartphone cameras as it goes by – then stitched the video segments into a short video. Movement along a path with multiple angles I imagine looks pretty cool.\nImagine someone arranging this for a concert or even a theatrical presentation – if you can get 10, 20 or 100 people to hold their smartphones up for the entire performance or scene you'll have a modern, cool format to present the show to others. You could use videos from folks further away from the stage for transitionary segments or slower moving parts of the production or song then 'zoom in' to closer cameras for the important stuff. I'd love to see this done more – I bet some innovative folks can do some pretty interesting stuff with this technology.\nNow, I'm not a paranoid person (although just because you're paranoid doesn't mean people aren't out to get you), but the next important part of the article really scared me:\n&quot;For instance, the drones that patrol the U.S.-Mexican border and the security cameras in cities already record more footage than human observers can possibly examine. If an agency could rely on a computer to track individuals, groups and events on its own, agents could use intelligence far more—well, intelligibly.&quot;\nWe're hearing more and more about law enforcement organizations using social media such as Facebook and Twitter to identify criminals from event images and social media posts. That the technology described in this article could be used for tracking people through a city really scares me. When you think about it though, they don't need any special algorithms to do this today. Many governments already have the facial recognition software they need and multiple camera angles to pull from to create sophisticated videos from crime scenes. Cameras are everywhere, put there using the paranoia generated by the September 11, 2001 terrorist attacks in the US. Assuming someone could coordinate the timestamp of multiple videos (clocks on video recorders are set manually today right? Enabling them to be set via atomic clock would make this easier), we're not far away from being able to see everyone in a crowd from multiple angles after a terrorist event or serious crime.\nThe good news is that this technology will make it easier to catch criminals and terrorists. The bad news is that these cameras are everywhere and there is very little to keep governments (or even criminals) from watching your every move. For any Rush fans out there – this is exactly what's described in Red Barchetta.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Telemarketed by an IVR",
  "date":"Wed Dec 26 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1356566400,
  "url":"/posts/2012/telemarketed-by-an-ivr/",
  "content":"I just got a telemarketing call from an Interactive Voice Response (IVR) system. I was sitting in my office and a call came in from a number I didn't recognize. When I answered, there was a long pause, so I knew someone was telemarketing me. After a while, I usually say something smart-allecky like 'hello? You called me?” and hang-up if the pause lasts too long.\nIn this case, a very steady, professional and rich voice clicked in and said “Hello, may I please speak with John?” Still in smart-alecky mode I said “You got him, what do you need?”  There was a long pause and the exact same voice said the exact same thing: “Hello, may I please speak with John.” I told the system in a smart-alecky way that they'd gotten me, but the system clearly couldn't handle my smart-aleckiness, got confused and eventually hung up on me. \nI'm used to getting telemarketing calls where there's a pause while they connect you to an agent once the system has determined that an actual human has answered the phone. I usually hang up before the agent can say anything. In this case, the number being called is listed in the US National Do Not Call Registry, so there never should have been a call anyway. Ugh.\nWhat's interesting about this though is that the newer systems apparently have this IVR in front, either to do triage like make sure the target is on the phone before connecting the call to an agent or to handle the call completely. Surprising though that the IVR wasn't able to handle the call. What's the point? I answered and said that they'd reached John – how horrible is the system if it can't even handle that little bit of conversation.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Cloud-based Hosting",
  "date":"Thu Dec 20 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1356048000,
  "url":"/posts/2012/cloud-based-hosting/",
  "content":"Saw this in an email tonight from Network Solutions. Since when is hosting not cloud-based?\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Lands' End Track Order Stupidity",
  "date":"Sun Dec 09 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1355097600,
  "url":"/posts/2012/lands’-end-track-order-stupidity/",
  "content":"I'm a huge fan of Lands' End (yes, that's a typo – it's their typo, not mine) and have been a customer for a very long time. Everyone's on the Internet now, so you can buy things, check status of orders and even return stuff without ever having to fill out a form or even call a customer service person.\nWhy is it then that Lands' End won't give you an easy way to track your order?\nI got an email from them for an order I placed (shhhhh, it's a gift for my Wife) that included the track order button shown in the figure below:\n\nFigure 1 – Lands' End Shipped Order Confirmation Email\nBeing interested in knowing where said order was, I clicked said Track Order button and was presented with the following page:\n\nFigure 2 – Lands' End Track Order Page\nHelp me understand why they're prompting me to enter my order number? They already know what my order number is – they're the ones who sent me the email listing the order number (which I've blurred out in Figure 1. They even know what country I'm interested in as well as the zip code).\nIt's the Internet age; we're all surrounded by this amazing software that automates so many things we had to do by hand many years ago. In this case, Lands' End knows who I am, knows all sorts of information about my order and they're politely giving me a way to check the status of my order's delivery by sending me that email. They've apparently chosen to ignore all of that information and force me to enter in information that we both know that they already know.\nWhen I receive an order status email from Amazon for example, the link they provide takes me immediately to my order status page which lists the status of all of my orders. They make me login first, before showing me the information, but at no time to they ask me to enter information that they already know (except for my password – which I don't want them entering for me).\nIt's simply an example of someone not paying attention to how a piece of software functionality is actually going to be used. In this case, when I get to the order status page, I don't have the order number. I could login and get it, or I could switch back to my email client to get it, but either way, the 'track order by number' page they provide me provides me with no value by itself, I need information from another source. That being the case, then what's the point of even showing me that page?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Spain's Secret Strike",
  "date":"Fri Dec 07 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1354924800,
  "url":"/posts/2012/spain-secret-strike/",
  "content":"I was in Spain for a conference back in November and I was there during a nationwide strike against the austerity programs that the EU is putting in place to help enable economic recovery. My employer is international (we have offices and employees everywhere) and very organized, so we knew a lot in advance about the strike and were given very specific instructions on how to stay safe during the… unrest.\nAfter I'd been in Spain for a day or two, I realized that there was a Secret Strike happening right in front of us. The purpose of this post is to bring information about this secret strike to light so others can learn about it.\nSpain's Secret Strike is all about Heat!\nI'm one of those people who like to stay cool. Being hot, especially too hot for no reason, drives me crazy. I don't mind making myself hot – through activity or exercise, but being hot simply because someone has the furnace on too high simply demoralizes me.\nRight about the time of the strikes, all of a sudden everywhere I went  the internal temperature in my hotel room and in the conference center was much higher than I found comfortable. When I arrived in Madrid, my hotel room was comfortable and the rooms at the conference center were actually cold (which is surprising).  Starting Tuesday, the public strike (not the secret one) was supposed to be on Wednesday, all of a sudden the conference center got much warmer and the same for my hotel room.\nI asked at the conference desk Tuesday afternoon if it was hot on purpose and I was told no and that they'd been asking repeatedly to have the heat turned down. At this time, it was 26 degrees C (78.8 degrees F) which is mighty uncomfortable when you're wearing a suit all day. Ugh.\nThat night, my hotel room was hot, too hot for me to sleep. Of course I couldn't open the windows (locked) so the next morning I politely (or at least I thought it was politely) asked at the front deck if they could make my room a little cooler. When I arrived back in the room that night, it was a balmy 29 degrees C (84.2 degrees F). Ugh – by asking to make my room cooler – they made it unbearably hot. Double ugh!\nNeedless to say, I was unable (through multiple attempts) to get my room or the conference center where I was working to a temperature I could sleep/work in. I thoroughly enjoyed being in Spain, but unfortunately couldn't wait to get out of the country simply so I could stop sweating for no reason.\nDiabolical those Spaniards – keep the world's media focused on the 'public' strike while secretly wearing us down by refusing to turn down the heat. Simply diabolical!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Mobile on WordPress",
  "date":"Sun Dec 02 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1354492800,
  "url":"/posts/2012/mobile-on-wordpress/",
  "content":"I've been doing a lot of work in WordPress lately. I've always been a fan of the wildly popular, Open Source Content Management System (CMS) but I've always thought it was more appropriate for web logs (blogs) than company web sites. Of course, many companies use WordPress for their web sites, and there are even commercial offerings for business customers, so I know it's common to find business uses for WordPress.\nThis summer I worked with some neighbors who were opening a boutique olive oil and balsamic vinegar store in South Charlotte called Olive This! (olivethis.com). As I consulted them about what they wanted to accomplish and their potential skill set, it was clear that WordPress was the way to go for them. I quickly setup a site, populated some menus and got them going. It wasn't long before they took over the site and now it's truly a thing of beauty. My only involvement going forward is to provide some occasional support when something weird happens or when they want to add something new to the site and don't know how.\nFor many years I've had a personal, family web site (different from this, my technical blog site). I first set it up when I was learning Joomla and made a Joomla site for the home page. Over time, I picked up WordPress and added it as a sort of blog underneath the Joomla site. Of course, it didn't take me long to figure out that what I'd done was pretty stupid, having two CMS running essentially the same site made no sense. Unfortunately, it wasn't until years later (just about a week or so ago) that I decided to whack the Joomla site and move everything to the WordPress site. I did that and I'm really happy with the new site. It's clean, simple and does exactly what I need it to do.\nFor many years, since the late 1980's actually, I've had this side company calledMcNelly SoftWorks. Over the years, I've assigned all of my copyrights to the company and done any side work under the company's name. Back in 2005, after I sold my shares in a Northeastern Ohio-based software and consulting firm, I ran McNelly SoftWorks as a full-time business and even created several commercial software products that are still available for sale today. About that time, I created a web site for the company using NetObjects Fusion – a web site generator that at the time was pretty interesting and cool (to me).\nOne of the long-term items on my to-do list though was to migrate the company's static web site I created using NetObjects Fusion to something more dynamic. I originally thought I'd create it using Joomla (joomla.org) or perhaps Concrete5 (concrete5), but never got around to doing anything with it. Last week I finally got around to doing something with the site and I'm very happy with the results. The coolest thing, and the primary reason for this post, is that everything I did for the site was automatically mobile device friendly – simply because of the tools I selected to create the site.\nLet me explain what I mean…\nFigure 1 shows the new McNelly SoftWorks web site I launched this weekend. The site was created using WordPress and a very simple and clean template I found called Tiga (https://wordpress.org/extend/themes/tiga).\nAs I setup the site, I wanted the company logo and a simple menu at the top and the content filling most of the rest of the page. For the products area, I added a sub-menu which I was very easily able to assign to the right column of the page with the article content listed on the left. Overall, I really loved the simplicity of the site and how clean the UI was. I worked Friday night and Saturday morning on the site and was very happy with the results.\n\nFigure 1 – McNelly SoftWorks web site\nMy son had a cub scouts meeting on Friday and as I waited for his meeting to wrap-up I fired up my BlackBerry browser to see how the site looked on the device's smaller screen. I was very surprised to see that the site was completely mobile friendly and looked amazing on the BlackBerry.  Looking back, I noticed that the Tiga template was listed as being mobile friendly – I'd completely missed that when I selected it. Figure 2 shows the site on my BlackBerry Bold 9930 device browser.\n\nFigure 2 – McNelly SoftWorks Home Page on the BlackBerry Browser\nOn the BlackBerry side, the BES or BIS services pre-process the web content automatically to make it better fit on the smaller BlackBerry screen. In this case, the BES or BIS Service resizes images to fit the screen. That capability coupled with specific settings on the Tiga template made the site simply render beautifully on the BlackBerry. Notice in the figure that the logo has been resized to fit the screen and that the menu is shifted from the right side of the page to directly below the logo.\nWhen you open the products page shown in Figure 1, the 'side' menu gets added, but because of the limited real estate on the BlackBerry screen, it's shifted by the template to immediately below the page content as shown in Figure 3.\n\nFigure 3 – McNelly SoftW",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "SAP CodeTalk Series",
  "date":"Sun Aug 19 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1345420800,
  "url":"/posts/2012/sap-codetalk-series/",
  "content":"SAP has started producing a series of developer-focused videos. The series is called SAP CodeTalk, and I was asked to participate in the first two videos in the series. You can find the series landing page at https://youtube.com/playlist?list=PL068D7CC6E905E638.\nThe first video was recorded with Matt Schmulen from Appcelerator and in the video we talk about how to connect to SAP from an Appcelerator Titanium application using the new OData connector from Appcelerator. You can watch the video here: https://youtube.com/watch?v=cSYu2Np_U_U.\nThe second video was recorded with Edmund Leung from Sencha and in the video we talk about how to connect to SAP with a Sencha Touch application using Sencha's new OData connector. You can watch the video here: https://youtube.com/watch?v=cYtYxifrb20.\nBoth videos wrap-up with a code demonstration, hence the CodeTalk series name. I'm planning on doing a few more of these as we do further integration with Appcelerator and Sencha. Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PhoneGap and Metro",
  "date":"Sun Aug 19 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1345420800,
  "url":"/posts/2012/phonegap-and-metro/",
  "content":"Apparently the folks at PhoneGap have decided to adopt the Microsoft Metro interface for the PhoneGap web site (phonegap.com). It's pretty cool what happens when you resize the browser window - whoever implemented this really paid attention to that particular detail. Cool stuff.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "ClearOS Server",
  "date":"Wed Aug 08 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1344470400,
  "url":"/posts/2012/clearos-server/",
  "content":"After I became a Novell ECNE and CNI, back in the 80's or early 90's, I promised myself that I wouldn't have a network in my house.  Now, my office has a 24 port switch and 9 computer systems (including two Macintoshes) and I've networked two buildings here on the property. Oh how things have changed.\nI've had a Windows server here for a very long time – it has 6TB of storage and I use it to backup all of my other systems (I backup my primary Macintosh computer to an AirPort in a different building). I also sync all of my iTunes music (a lot of it and ALL legal) to it, then stream it from the server to my Sonos box (I LOVE SONOS!!!) connected to my office stereo.\nI recently upgraded the home stereo and have really enjoyed RadioIO, Pandora and other music services playing on the stereo. What I miss though is access to my music library. Sometimes you simply want to hear everything you have from a particular artist or listen to a particular CD, and the services my stereo can access don't support that. I'm waiting for Sonos to add support for Spotify.\nThe new stereo can stream music from a media server, but my Windows Server 2008 box doesn't include one and I couldn't figure out how to add it to the server. I downloaded the Wild Media Server, but it wouldn't let the receiver connect to it no matter what I did and the answer I got from the Wild folks was a recommendation that I not use their software. Crikey!\nI was thinking of upgrading my server to the latest Microsoft Small Business Server, but instead was reading Robert X. Cringely's column about cloud computing and the ClearOS I thought I'd install that OS on one of my boxes and see if I can use it as a replacement for my Windows server.\nRight now I only have Sonos boxes in my workshop and my office. If I can get the media server working, I can finally listen to all of my music in the house. Wish me luck!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Joomla Upgrade",
  "date":"Mon Aug 06 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1344297600,
  "url":"/posts/2012/joomla-upgrade/",
  "content":"I'm knee deep into a major upgrade for this site. I've been running it on Joomla 1.5 for years now and I thought it was time to get caught up on Joomla versions. Of course, there's no simple path from Joomla 1.5 to 2.5, so I had to do a migration. There's a cool migration tool called jUpgrade that essentially copies your existing site to a new folder and migrates all of the content. It worked like a champ and I'm in the process of doing all of the clean-up that has to happen.\nThe biggest reason I'm doing this is to get on the latest version, but to also update the site's look and organization to bring it in line with other sites of its kind. I'm a big fan of the Joomla templates from JoomlaShack (joomlashack.com) and had been using a variable width (full width) template layout, but none of the new, more modern templates from them support that layout. Ugh. So, in order to use one of their new fixed-width templates, I had to whack one of the side bars and move everything into a top menu.\nI've got that finished and now I'm simply working to reenable all of the features of the site. The comments, attachments, code highlighting add-ons I'd been using with my old site are not compatible with Joomla 2.5, so I have to locate an appropriate substitute and get it implemented. Unfortunately on the attachment and code highlighting side, it means that I'm going to have to go and update all existing articles that leverage those features. Not going to be fun.\nJoomla includes a code highlighting module, but I've never been able to find any useful instructions on how to use it. The one I'd been using had different formatters for different languages, so it was pretty useful. Putting code highlighting back in is going to be the hardest part of this.\nI'll be writing a post that documents some of my issues with doing this upgrade – stay tuned. The new site should be up in a few weeks.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Olive This",
  "date":"Thu Aug 02 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1343952000,
  "url":"/posts/2012/olive-this/",
  "content":"I've been writing a bit about some friends of ours who have opened a specialty olive oil and vinegar store in South Charlotte called Olive This!. Simply two housewives with an idea and a well-known distributor with a quality product. When I heard about what they were doing, I knew they'd need a web presence and immediately offered to help. I would have done it for free, but instead they plied me with cookies, brownies and other food items for my help.\nI set them up with a hosting account (at Fatcow of course) and a quick installation of WordPress. I guided them through the process of setting up their site's structure and a little about the site's look (I am NOT a designer). We got it pretty far before one of the partner's husband (who is very talented) jumped in and started creating graphics for the site and tweaking the site's content and look. It turned out beautifully and just went live this week at olivethis.com.  They even created a Facebook page for the business.\nHere's a shot of the web site, it looks great:\n\nOnce they opened, some of their initial customers were involved with different publications in the area, so they're already getting some great publicity. The first was an article in the local community paper about new stores in the area (https://charlotteobserver.com/2012/08/01/3407032/new-stores-opening-all-over-the.html) but I imagine more will come soon.\nIf you get a chance, swing by their store Olive This! – it's located near Trader Joe's at 6414 Rea Road, Charlotte, NC 28277. Their hours are Sunday from 12 PM to 5 PM &amp; Monday through Saturday from 10 AM to 6 PM. You can reach them by phone at 704.544.8099.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "News from SAP Labs",
  "date":"Sun Jul 08 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1341792000,
  "url":"/posts/2012/news-from-sap-labs/",
  "content":"Since joining SAP, I've been heavily involved in our partnerships with Adobe, Appcelerator and Sencha. I'm still trying to carve out some time to play with the new tools we've created in partnership with these vendors, but I've been too busy working on developer enablement activities. One of the things I'm working on right now is preparation for a streaming video presentation from the SAP Labs about these partnerships. I'll be on camera, ding interviews and other fun stuff.\nIf you get a chance, check out this session:\nNews from SAP Labs: Making it simpler than ever for developers to build mobile apps for business - Use Adobe PhoneGap, Appcelerator Titanium and Sencha Touch to build mobile apps for SAP and OData\nDate: Monday, July 30, 2012\nTime: 8:00 AM Pacific Daylight Time\nJoin us for this webcast streamed from our development labs in Silicon Valley and see how SAP makes it simpler and more profitable than ever for any developer to enter the growing market for enterprise mobile apps. The webcast will be a part of a very exciting announcement from SAP showing our continued commitment to deliver a comprehensive mobile developer experience.\nThe webcast will feature integration options using OData and the Hybrid web container presented by Adobe, Appcelerator and Sencha developers and will host mobile apps partner Above Border who have successfully developed mobile apps for SAP customers.\nBe ready for lots of innovative mobile app samples, demos and useful information to help you get started and take advantage of the growing mobile opportunity in the enterprise market.\nHow to participate in the Q&amp;A session:\nIf you have a Twitter account, use #SAPQA #Mobile to send your questions during and 1-hour after the webcast. Please use the same hashtags to share your comments and to follow the conversations.\nTo register for the event, please use the following link: https://bit.ly/LClcmh\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "New Soccer Referee",
  "date":"Mon Jul 02 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1341273600,
  "url":"/posts/2012/new-soccer-referee/",
  "content":"My first book was a Soccer Referee book called What Now? The Essential Guide for New Soccer Referees. I'd officiated for about 23 years and when I retired I decided to write a book and share all those tidbits I learned that could help a New Soccer Referee get started. The book's been on sale since 2007 and I'm still selling a few copies a month. Just for fun I spent a little time today updating the web site for the book. The site is at newsoccerref.com.\nI have to get updated flyers made, I've moved since the book was published, and I'm thinking of adding a sample chapter or part of a chapter to the site.\nPlease think of me if you know of someone who wants to get started as a New Soccer Referee.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "PhoneGap Books",
  "date":"Fri Jun 08 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1339200000,
  "url":"/posts/2012/phonegap-books/",
  "content":"There's a site out there that contains information about each of the PhoneGap books on the market.It's called appropriately enough PhoneGap Books (phonegapbooks.com).\nNo entry for PhoneGap Essentials yet, but I'm sure that will get fixed once the book is actually on the market.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "RhoMobile & Domino Article Part 1 & 2 Published",
  "date":"Wed May 23 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1337817600,
  "url":"/posts/2012/rhomobile-domino-article-parts-1-2-published/",
  "content":"As I mentioned previously, I wrote a long (4 part) series of articles for The View on how to use Rhomobile Rhodes and RhoConnect to mobilize a Domino application. Well, I'm a bit behind notifying you that Part 1 and Part 2 of the article series have been published.\n\nPart 1 is entitled Mobilizing Domino Data Using Rhodes and RhoConnect, Part 1 — Getting Started. The article provides a detailed overview of Rhodes and RhoConnect plus shows how to create a simple Rhodes application (that will be enhanced in subsequent articles). The figure to the right shows the simple default Rhodes application we'll be enhancing in the article series.\nPart 2 is appropriately named Mobilizing Domino Data Using Rhodes and RhoConnect, Part 2 — Testing the Demo App and covers how to use the different tools Rhomobile provides to help you test and debug your Rhodes applications.\nPart 3 is in the edit process and will hopefully be available soon. It covers how to add a data model to the Rhodes application and adjust the application's UI to meet your requirements. Part 4 covers in detail how to use RhoConnect to synchronize data between the Rhodes application and the Domino application. I'll let you know when those are online.\nI also wrote a bonus 5th article that highlights some of the tricks I had to use to debug the sync process as I coded the RhoConnect and Domino applications.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "What Were They Thinking 12",
  "date":"Tue May 08 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1336521600,
  "url":"/posts/2012/what-were-they-thinking-12/",
  "content":"The BlackBerry World Application (yet again)\nFor several years now, I've been writing articles for this site that analyze poorly designed mobile applications.  It has always amazed me how mobile application developers just don't seem to think about how their applications would be used and the 'What were they thinking?' series of articles was born. It rarely takes me more than a few seconds to see where these applications fail.\nAs I prepared to attend BlackBerry World, I of course downloaded the application for the conference and quickly saw that I would have yet another 'What were they thinking?' post centered on the BlackBerry World application. \nIt just doesn't make sense – why do they continue to produce unusable applications for the conference? Isn't this supposed to be their showcase conference? Isn't the BlackBerry app for the BlackBerry conference supposed to be the best of the best? Don't they know how to build cool and useful apps for BlackBerry? They're BlackBerry, right? The BlackBerry Travel app is amazing, why is the BlackBerry World conference application so…challenged?\nLet's take a look at the app. When I first launched the application, I saw what's shown in Figure 1.\n\nFigure 1\nThe first thing I noticed was that it appears that the only option available to me is the 'Share This' option. All of the other icons appear to be disabled. I seriously spent the 30 seconds or or so trying to figure out why all of the application's options except for 'Share This' were disabled.\nTaking a hint from Windows or Mac OS, disabled options usually appear without any coloring so users can easily tell which ones are enabled and which are not – just like most of the icons appear on the screen shown in the figure. There's no shadow or highlighting that would make me believe that those other options were valid. When designing a mobile application, if you're going to have a bright blue icon and you don't want your users to think all of the other options are disabled, you have to use color on each and every icon on the screen.  The only other option is to use no color at all – for all icons on the screen.\nThis particular effect is even more prominent in the BlackBerry 10 Jam application shown in the figure below. In this example, the icons look even worse. Clearly nothing except for 'Share This' is a valid option, right?  The dull grey tone of the remaining icons on the screen screams 'this option is disabled.'\n\nFigure 2\nThe next thing I noticed in Figure 1 is that this is a browser application (see the 'mouse' cursor in the upper-left corner of the screen?) The first thing I did was swipe on the device's touchpad to scroll through the options (the icons) on the screen. No can do, the touchpad does nothing but move the mouse cursor. You can touch the screen to click the icons, but if you use the little optical touch pad, all you can do is move the cursor around on the screen (and click buttons). What an inefficient input mechanism.\nAs a developer, you have access to the touchpad and you could use JavaScript code to take that motion and translate it into something that highlights each icon as you swipe across the touchpad. Even if you didn't have direct access to the touchpad input, you can still track 'mouse' movement and know that the first down motion of the 'mouse' should highlight the first icon (sessions) then as the 'mouse' moves left/right/up/down, move the highlight to the appropriate icon as needed. Oh, right – there is no highlight, all the developer created were these lackluster icons.\nWhoever developed this application didn't take into account users like me who has a BlackBerry Bold and didn't want to reach all the way up (no, I'm not lazy) and touch the screen when I could simply use the touchpad. You have to accommodate both input mechanisms – touching the screen and using the touchpad. To ignore one and assume the other is poor application design.\nWhen you scroll down the page, you see what I'm showing in Figure 3. Why did the developer feel the need to use a background graphic that's far bigger than what is needed for the application? When you scroll to the bottom of the icon list, it should stop immediately below the last screen element displayed. It should not take up so much additional space on the screen. There's no need to waste the space like this.\n\nFigure 3\nNow, I know the developer setup that background image to accommodate all of the icons that appear after you login. But why not show all of the icons, only disabling the ones that are not active – that way, this scrolling issue goes away and with that little extra effort you would have been able to tell that some icons were active and others inactive.\nAll that aside, I can't seem to use the application since when I start it, I get the following error and I can't do anything with my schedule.\n\nFigure 4\nOn the second day of the conference, RIM released an update to the application, but because I didn't get around to updating it. However, it doe",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "BlackBerry World Day 1 Begins",
  "date":"Mon Apr 30 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1335830400,
  "url":"/posts/2012/blackberry-world-day-1-begins/",
  "content":"Got up early this morning and made it over to the hotel's gym. It was nice to get some exercise in before starting my day. When I finished, I decided to walk around a bit just to get my back loosened up. As I walked past the BlackBerry World registration desk, I thought about my registration process and thought I'd write about it.\nThis is my 6th BlackBerry World (or Wireless Enterprise Symposium, WES, as it used to be called), so I knew exactly what to do. I walked toward the registration area, following the signs and walked up to the registration tablets. Of course RIM uses the BlackBerry Playbook for registration, makes sense. Of course, there's always someone there to make sure you know what you're doing – as I walked up purposefully to one of the tablets, she asked me 'You here to register?'  I'm not sure what else I'd be doing in the Registration area, but yes.\nAnyway, as I typed away at the registration process, I truly struggled. For some reason I just couldn't type my email address (all that's needed for that part of the registration process). I love my BlackBerry Playbook; I use it all the time. Suddenly I kept mistyping then having to back up and fix the text I just typed. Embarrassing. It wasn't until I walked past the registration desk this morning that I realized why. The tablets were attached to the table using Velcro! Of course I couldn't type on them – they're designed to be held in your hand not strapped to a table. The angle was all wrong. If I'd been able to pick up the tablet and use it like I always use it, I wouldn't have had problems with the registration process.\nI understand the need to keep the tablets from walking away, but they should allow me to use the device in the manner in which I'm accustomed. Not force me to use it in an unnatural way.  Attach it to the table using some sort of cable; accommodating both left- and right-handed people and you'd have a better experience for registrants.\nOnce the application showed me that my registration had been accepted, it told me to go to badge pickup area B to get my credentials. As I walked away, the handler, the girl watching everyone register, told me I had to click the finish button to finish the registration process. This isn't critical, but I think this is an application design issue that needs to be addressed.\nThe finish button was a standard web browser button that I'd completely missed because it was too small for fingers. When the application told me to go to badge pickup area B, I immediately attempted to walk away from the station to pick up my credentials. That's expected behavior, right? Why do I need to click the Finish button? The application knows I'm finished, why not leave the information up there for 15 or 30 seconds or so before moving on to the next screen itself rather than force me to click the button as I leave? Another option would be to put up a 'Next Registrant' button or something so that if someone else comes up before the 30-second window had completed (which is highly likely during the first 24 hours of the conference).\nWhat they should have done is use up more of the screen real estate for the button, so it's more easily seen and, very importantly, large enough that the user can easily click it as they're walking away from the table. I found that because of the limited space allocated for the button that I had to force myself to stand still and concentrate on getting my finger within the button borders. If they'd used a much bigger button, I could just have swiped at it as I was leaving.\nThis is a perfect example of what happens when a developer designs, develops and tests an application outside of the environment where the application will be used. I imagine that if the developer had to test the application while standing up and while the tablet was strapped to a table, that he (or she) would have made some adjustments to the application's UI before putting it into production.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Figured out PhoneGap Development for bada",
  "date":"Thu Apr 26 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1335484800,
  "url":"/posts/2012/figured-out-phonegap-development-for-bada/",
  "content":"If you remember a while ago I published an article that explained some of the issues I encountered trying to build and run a PhoneGap application for the Samsung bada OS. Well, with the help of the developer who wrote the bada code for PhoneGap I was able to finally figure it out, get it working and finished the bada chapter for PhoneGap Essentials.\n\nFirst I'm going to complain a little and then I'll tell you what you need to do to build PhoneGap applications for bada.\nMissing Files\nIn the article I pointed out how the files you needed to build a bada application using PhoneGap weren't actually in the PhoneGap download. I just checked in the PhoneGap 1.7 release candidate download and they're still not there. I simply don't understand it. The development team knows the wrong files are included in the download, but months and months later this particular problem still hasn't been fixed. How hard can it be to make sure the files you need are packaged into the download? I discussed this with them months ago – you would think this wouldn't be hard to fix.\nBeta\nDid you know that support for bada in PhoneGap is considered beta? No, neither did I. The reason the instructions I needed to understand how to build PhoneGap applications for bada were not available is because the PhoneGap project considers (or considered) support for bada to be in beta status. I wish they'd told me that when I started.\nWrong SDK Version\nOK, the reason why I  (and all of you) couldn't get the bada stuff to work, even when you had the right files, is that the bada code (still being beta and all) was written for and will only work for an older version of the bada SDK which is no longer available for download. Perhaps I missed this when I started working with this back in August, but I finally see it listed in the readme:\nDISCLAIMER: THIS IMPLEMENTATION DOES NOT WORK WITH THE BADA 2.x SDK. ONLY 1.2 is supported BY THIS IMPLEMENTATION!\nSo, in order to be able to use this for your bada applications, you will have had to already downloaded this older SDK (before Samsung pulled it from their web site). If you didn't do that, you're out of luck.\nI just noticed too that actual instructions for building bada applications for PhoneGap are now posted to the PhoneGap web site: https://phonegap.com/start#bada.\nConclusion\nSo, now you know what you need to build bada applications using PhoneGap. As I understand it, the PhoneGap development team is working on an update to the code that will work with the bada 2.x SDK. This will essentially be a complete rewrite since 2.0 does things differently. Once that is done, building bada applications will be easier since you'll be able to use the latest SDK, support the latest devices and have a simpler process for starting a new app (I hope).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Error Capturing Video using PhoneGap",
  "date":"Wed Apr 25 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1335398400,
  "url":"/posts/2012/error-capturing-video-using-phonegap/",
  "content":"I got up early this morning to answer some last minute questions from my editor for PhoneGap Essentials. We're almost done with the book; I just had a few questions to answer. The editor asked me to redo one of the screen shots because it was a little blurry. I dug out the device I used to take the screen shot and setup the shot. The device battery had died, so I plugged it into power so it would charge as I began my test. As I loaded the application and started the video capture application used in the book, the application threw a couple of errors.\nOn this particular device, video capture is disabled when the battery life falls below a certain threshold. This makes sense, but in this case it shouldn't have mattered since the device was connected to a power source and was charging. Apparently it does.\nAnyway, that's not really important, what's important to me was how the application responded. As I wrote that chapter, I struggled to determine how to cause errors in the video capture process. I could of course cancel the capture and show readers what was returned to the PhoneGap application, but I was looking for real errors and finally found one. The trouble is, the information returned from the PhoneGap application wasn't enough to help me as a developer understand what had actually happened to cause the failure.\nLet's take a look at what I mean.\nIf you take a look at Figure 1, you'll see a screen capture from the device as soon as I attempted to record video from the application. The alert box is the application's way to let me know what happened during the process. In this case, the device refused to take the video (because the battery was too low) and returned a canceled error to the PhoneGap application.\n\nI didn't notice at first, but the device also displays (for a very short time) an error indicating why it can't capture video. It wasn't until I'd tested this a few times that I noticed that little pop-up below the alert dialog.\nUnfortunately, no error code beyond the simple cancelled message is returned to the calling program, so there's no way for the PhoneGap application to tell what actually happened and recover cleanly. All the app knows is that the video capture failed, not why.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Rhomobile & Domino",
  "date":"Wed Apr 18 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1334793600,
  "url":"/posts/2012/rhomobile-domino/",
  "content":"As part of my role as a technical advisor to the View I decided a long time ago to start writing a series of articles demonstrating all of the different possible ways to mobilize a Notes or Domino application. I had a bunch of ideas and a bunch of different tools I wanted to play with, so I got to work. The cool thing about this was that I wanted to learn these tools, but had so many other things going that I just couldn't find the time to do it. Fortunately, writing a magazine article about a particular piece of technology is a great way to motivate someone like me to learn the technology.\nOne of the products I've always been interested in learning is Rhodes and RhoConnect, two products from Rhomobile (now part of Motorola Solutions, the other Motorola Company, the one that didn't get purchased by Google). I first learned about them while working at RIM and while something that interested me, I never found the time to work with it. I'd poked and prodded at it every so often, but I just couldn't get my hands around what it was, how it worked and so on. I finally found a book on the subject and on a trip back from the West Coast I read through it and decided I could make it work.\nFortunately when previous employer shortened my two week notice and my current employer wasn't ready for me yet, I created a simple Notes application they set about building the Rhodes application that connected to the database using RhoConnect. It was a challenge, but I got it all working and penned a series of articles on the topic. They're all submitted to The View and hopefully should be published soon.\nThe folks at Rhomobile helped me out a bunch – there was some weirdness surrounding some information the Domino server needed to return to RhoConnect after creating a record. It all made sense, but I had difficulty understanding if it was working or not. Of course, I had a stupid coding error that I'd missed, but once that was gone I got it working, but didn't know that it was. It's a long story, you'll have to read the articles to hear it.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "4,500 Records",
  "date":"Wed Apr 04 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1333584000,
  "url":"/posts/2012/4500-records/",
  "content":"I came across this press release yesterday:Mobiquity Takes Buildium Mobile; App for Property Management Software Leader Has Native-Like Scrolling. The article explains how the developers were able to build a PhoneGap application that allowed mobile users to scroll through a listing of up to 4,500 records with native-like performance and functionality. While that's probably a pretty good accomplishment, I have to ask why it was ever even done.\nWhy would you ever want to expose more than four thousand records on the screen to a mobile user at one time? It's great that they were able to accomplish this, but I'm pretty sure they solved the wrong problem. Instead of doing all of that work to make a hybrid mobile application (a native application built using web technologies) capable of displaying that many records, they should have designed the application so the user would never need to view that many records. Use search or filtering to allow a mobile user to quickly slice and dice the available data options to more quickly get to the data they need - rather than doing rocket science so they can scroll through 4,500 records smoothly.\nWho cares that the scrolling was jerky and slow - the user should never have (ever) been exposed to that much data at one time anyway. Can you imagine what this application is going to do to the user's data plan limits and battery life? It doesn't matter that you've solved the problem in an elegant and efficient manner - you never should have tried to solve that problem anyway.\nA developer has to constantly think about the impact their decisions have on the mobile user, application performance, network/data utilization and battery life. I can't imagine that was done in this case.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "New Job",
  "date":"Tue Apr 03 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1333497600,
  "url":"/posts/2012/new-job/",
  "content":"You may have noticed that I haven't posted much in a while. Lots going on in my professional life and I've been a bit busy.\nI resigned from AT&amp;T a few weeks back. I should't go into why I left, let's just say that it didn't end well.\nI have accepted a position at SAP. I'm in the Mobility Solutions Management group - which is SAP's name for customer-facing product management. I'm really excited to be working at SAP and to be back working for a software company again. In my new role, I've been assigned responsibility for Developer Experience - which means I'll have my hand in most any mobile development tools we create. As you can imagine, I'm pretty excited about this.\nIt's important to note that anything I post here, and I am going to have to make this a disclaimer on all posts from now on, reflect my personal opinion and in no way reflect the public statements or opinion of my employer.\nStay tuned, this is going to be fun.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Interesting Spam – Airline Ticket",
  "date":"Mon Apr 02 2012 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1333411200,
  "url":"/posts/2012/interesting-spam-airline-ticket/",
  "content":"I just received yet another interesting spam message in my inbox. Well actually it wasn't in my inbox; Outlook recognized it as spam and quarantined it – I'm surprised Norton Antivirus didn't catch this one (because of the likely infected attachment).\nAnyways, here's a screen shot of the email.\n\nWhat I imagine happens is someone gets this email and goes “Crikey, I didn't buy any plane ticket” and opens the attachment to see who purchased a ticket. Of course they open the 'ticket' and get infected. It must work since I've received many of these over time.\nI don't get it, how do people actually fall for this. Have any of you ever received an email attachment with an airline ticket from an airline? No, tickets come to your inbox – as an email message, not an attachment after you've checked in. No airline that I can think of has ever sent tickets in advance of checking in – even if they did, they wouldn't zip it. They'd send it as a PDF file (which is already compressed).\nYou'll notice that the itinerary information doesn't list the name of the departure city – that alone would tell me that it's a scam – where you're leaving from is as important as where you're going to. Right?\nOf course, Outlook hides the message routing information from me, so I can't look to see where the email actually came from. In this case, the email address shown as the from email is correct – it would go to Delta Airlines if you replied. However, it wouldn't actually get to anyone since all the spammer wants you to do is open the attachment; if you don't do that, he doesn't care what else you do.\nOf course, this email was written by someone who doesn't speak English as a primary language:\nYour bought ticket is attached to the letter as a scan document.\nYou can print your ticket.\nThank you for using our airline company services.\nWhat was it that PT Barnum said?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "US Air Doesn't Care",
  "date":"Sun Mar 04 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1330905600,
  "url":"/posts/2012/us-air-does-not-care/",
  "content":"Living where I do, I take US Airways flights most of the time. I'm regularly surprised by their inability to use technology effectively and it saddens me. I was checking in for today's flight this morning and decided I wanted to give them some feedback. On the registration form, they asked me for my name, email address and frequent flyer number. Unfortunately, I was already logged into the web site, and this was all information they already had. Why ask me for information when you already have it?\nI gave them some suggestions and during the process of typing them all in, I discovered that they blocked my ability to put carriage returns in the message. Ugh. Why not let me list my questions/comments on a separate line. Makes no sense.\nAnyway, as I submitted my comments, I was struck by what I saw on the confirmation page (shown below). You can tell that they just don't care about customer service when they won't respond to customer comments for 5 to 7 days. To top it off, they even tell you about it - you'd think they'd want to hide the fact that they don't care enough about you to respond within 24 or 48 hours.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "PhoneGap & Samsung bada",
  "date":"Sun Feb 12 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1329091200,
  "url":"/posts/2012/phonegap-samsung-bada/",
  "content":"While working on PhoneGap Essentials, I got a chance to work with some mobile device platforms I'd not worked with before.  I did some work with webOS, but as soon as I got ready to write the chapter on webOS development for PhoneGap, HP announced it was killing the platform and the PhoneGap team added support for Windows Phone development. So, I whacked the webOS chapter and cheerfully replaced it with one on Windows Phone.\nAnother interesting one is Samsung bada, a 'newer' OS supposedly getting some traction in Europe and Asia. I covered the OS in PhoneGap Essentials, but since then Samsung's thrown their hat in with another mobile platform called Tizen (https://wikipedia.org/wiki/Tizen). There's been some talk of backwards compatibility for bada applications in Tizen, so you should be OK with what you know about PhoneGap and bada.\nWhat I learned while working on the bada chapter of the book is that there isn't any useful information about how to build PhoneGap applications on bada. Not in the PhoneGap download, not on the PhoneGap Google Groups forums, not on the PhoneGap wiki. I'm trying to work through this for the book so the information in the bada chapter is complete, but I thought I'd fill you in on some of the problems today – knowing that they'll be addressed by the PhoneGap development team as soon as they can. I just wanted to make sure you had this information since I just can't find real information anywhere.\nFirst of all, the PhoneGap download located here: https://phonegap.com/download-thankyou doesn't contain the code you need to build a bada application for PhoneGap. If you download the files from there and extract them on your hard drive then open the readme.md file in the bada folder, you will see something like this:\n\nWhat this is telling you is that even though there's PhoneGap source code for creating bada applications in the download you just downloaded, you'll have to go somewhere else to get the actual code you need. The instructions instruct you to import the sample bada project files into the bada IDE while the bada folder in the standard PhoneGap download doesn't contain the project files. Instead of using the bada files from the PhoneGap download, you instead need to get them from the Apache Cordova (the latest name for PhoneGap) git repository here: https://git-wip-us.apache.org/repos/asf?p=incubator-cordova-bada.git.\nOnce you download and extract the files, you'll have the files you need to import the bada PhoneGap project into the bada IDE.\nBefore you can run the program though, there's one more step you have to complete and this isn't documented anywhere either. Open Windows Explorer (the bada stuff only runs on Windows) and navigate to the bada source folder you extracted. Within the Res/phonegap folder is the phonegap.bat file highlighted in the following figure. You must execute that batch file to generate the phonegap.js file used by the sample application. I don't understand why you have to take this extra step, there's no reason I can think of that would prohibit the PhoneGap team from generating this file in advance, but it is what it is.\n\nIf you later make any changes to the JavaScript source files shown in the figure, you can just rerun the batch file to generate a new phonegap.js file from your modified source.\nAt this point you are supposed to be able to fire up the bada IDE, import the project and get to work. At this point, I've not been able to make the project build and execute on the bada emulator, but I'm working on it and you'll find the complete instructions in PhoneGap Essentials when it makes it to print.\nIf you did a quick Google search on PhoneGap and bada, toward the top of the search results should be the link to a PhoneGap bada tutorial here: https://groups.google.com/group/phonegap/browse_thread/thread/ee8dcd9ca0d2d792 Unfortunately those instructions didn't work for me. I followed the instructions to the letter and I got an application, but not one that would use any of the PhoneGap API's. The tutorial instructs you to build a bada web application to use with the PhoneGap API's, but if you look at the source code folders in the bada PhoneGap download, you'll see a bunch of C++ library files – which implies that it's not a web application, but instead a C++ application that the PhoneGap application runs within. Supposedly there are complete instructions available for how to do this, but I have not been able to get my hands on them. If you know how to make the instructions in this tutorial work, please let me know because I cannot.\nI'm still working through this and will update you when I have it working. Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Silly CAPTCHA",
  "date":"Tue Feb 07 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1328659200,
  "url":"/posts/2012/silly-captcha/",
  "content":"I was registering for access to the Sencha Forums today when I saw the following on the registration form:\n\nFigure 1\nThat's pretty advanced math for a CAPTCHA, isn't it?\nSo, is the math problem this:\n6 – (2 x 3)\nOr is it this:\n(6 – 2 ) x 3\nHaving a degree in Physics and more than 30 years of experience as a professional software developer, I was certain I knew what I was doing. However, I'd be lying if I told you I got this right on the first try.\nAll of my years of experience with math told me that the actual problem I was trying to solve was this: 6 – (2 x 3). Everything I knew from high school and college told me that without parenthesis clarifying the problem, the more complicated math happened first followed by less complicated. Even Wikipedia confirmed this here: https://en.wikipedia.org/wiki/Order_of_operations.\nThe answer's Zero, right?\nNope, that's not the case. So, not only is the registration forum asking me to do more complicated math than simple addition, subtraction or multiplication – but it's also scoffing at normal precedence of operators and essentially forcing me to give the deliberately wrong answer which, according to them, is 12.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "American Football",
  "date":"Sun Jan 29 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1327881600,
  "url":"/posts/2012/american-football/",
  "content":"If you know me, you likely know that I'm a big Soccer fan. I regularly irritate my wife by calling American Football...well, you know - American Football. It amazes me that the entire world (except for the United States and possibly Cananda) calls a sport Football but for us in North America it means something completely different. That being said, I've been trying to expose my son to the sport so he'll be able to fit in better than I do (wink).\nSo, for the last few years, I've actually tried to pay more attention to the sport. For last year's Super Bowl, I actually knew who was playing before game day - which is something very rare for me. I even watched the whole game and enjoyed it. This year, I took my son on a Carolina Panther Stadium Tour and the next day a friend of ours gave me two excellent tickets to watch a game, so I went.\nThe whole family even sat down the week before last and watched an entire afternoon of Football (there, I didn't call it American Football – although I wanted to).\nSo, I'm excited for the Super Bowl game on Sunday and I went to the NFL web site (nfl.com) to see when the game started. I, of course, was struck by a couple of things I saw there.\nFirst of all, today, less than a week before the Super Bowl, I couldn't find the start time for the game anywhere on the home page. It's the biggest thing happening in the NFL and nowhere on the home page does it say when the game is being played. Nope, nowhere. That doesn't make sense. Either they're clueless, and nobody thought to put the game time on the site (which is unlikely), or their arrogant and assume that the game time is something EVERYONE must know and there's no reason to put it on the web site.\nSomething else interesting was the advertisement at the top of the site's home page – shown in the following figure. Help me understand something – why does the NFL need to sell advertisements on their home page? The site is likely hugely popular and they get a gazillion dollars from their licensed products, why would they need advertisements? It makes no sense – they're a huge brand and can stand alone on their brand. Why would they possibly need ad revenue? Are things that tough at the NFL?\n\nOne of the things that bothers me is that on sports related sites, when you see a game time posted, in most cases, it's the start of the television Pregame activities, not the actual game time shown. I was planning on watching the Women's World Cup Final last year and was an hour off because of this – I dutifully sat down in front of the TV at the specified time only to find out that the game started an hour later. I had a plane to catch, so I ended up watching the whole game from a bar at the airport.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "BlackBerry About",
  "date":"Thu Jan 19 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1327017600,
  "url":"/posts/2012/blackberry-about/",
  "content":"I can't remember why, but for some reason I wanted to look at my BlackBerry device software version the other day, so I fired up the Options application and started typing 'about' as shown in the following figure. I noticed some interesting things and that prompted me to write this post.\n\nWhen you first launch the application, it displays a screen similar to the one shown in the following figure. I'm running a BlackBerry Bold 9900 and I absolutely love it. It's small, fast, easy to use and I just have to have a full keyboard – makes me more efficient.\nThe device is running BlackBerry Device Software 7, which I knew, but you'll notice that it's running Platform version 5.0.0.680. I've written about this before here, but I had to bring it up again. So many people incorrectly refer to 'BlackBerry OS' when what they really mean is BlackBerry Device Software version. In this case, I'm running BlackBerry Device Software 7, but the OS is actually 5.0. So, people who say BlackBerry OS 7 are referring to an operating system that technically doesn't exist (yet). RIM refers to it as BlackBerry 7 OS which in actuality means the OS running BlackBerry Device Software 7, not version 7 of the BlackBerry OS. Make sense?\n\nWhen you press any key on the device, the screen will switch to a different screen in the application. This of course makes it hard to switch to a screen capture application and keep the same screen on the display. To take the screen shots within this article, I had to leave the app on the previous screen to the one I wanted to screen capture, use Alt-Escape to switch to the home screen and launch the screen capture utility. The act of switching to another application would cause the About screen to switch so when I came back from launching the screen capture utility, the screen I wanted to capture would be on 'top' of the screen. I think perhaps that RIM needs to fix this, switching applications shouldn't advance the About screen to the next page.\nAnyways, the next screen of the application shows the Java license information as shown in Figure 3. This makes sense since the BlackBerry is a Java device. I like Java and one of the few big disappointments in my professional life is that I never got a chance to do a lot of development in Java (before I moved on to more sales or management roles). Oh well.\n\nNext came a screen that surprised me. Take a look at Figure 4, it shows a copyright notice from Nuance, the folks that currently own the rights to Dragon Naturally Speaking software. Now, the BlackBerry has had voice recognition capabilities for a very long time – before Android and definitely before iOS. Apparently Nuance provided the software that provided that capability. What's interesting about this is that Nuance is also the software behind the Siri service included with iOS 5.\nIt's interesting that the BlackBerry is running the same software (or a version of it of course) that makes Siri so popular. I tried to use Siri on my iPhone 4 yesterday and with every query I made of the application, it executed a completely different task than I asked it to perform. So much for that.\n\nNext came a notice from Qualcomm and WebKit. Qualcomm for some part of the Radio and/or processor chipset and WebKit because the BlackBerry (and every popular smartphone but Windows Phone) uses Apple's WebKit rendering engine to render web pages in the browser.\n\nThe next one surprised me, as shown in Figure 6, the BlackBerry device shows a copyright notice from the Android open source project. Now I know that the BlackBerry PlayBook allows a developer to package an Android application so it will run on the PlayBook, I wasn't aware of the same capability being available on BlackBerry devices. Apparently RIM's doing some work in this area (or something else related to Android) so that's why this notice is in the About Application. It will be interesting to see what RIM does with the Android support.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Wozniak & Android",
  "date":"Tue Jan 17 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1326844800,
  "url":"/posts/2012/wozniak-&-android/",
  "content":"I like my iPhone. It's got a cool UI and the apps are great. Unfortunately, I just can't use one day to day – there's too many klugy things about it. The BlackBerry has spoiled me with the keyboard, I can so quickly go to the top of a list (by pressing the 't' key), bottom of a list (the 'b' key), File an email message ('f' key) and most importantly use the keyboard to type the name of the folder I'm filing an email into.\nI get more than 100 emails a day and the way iOS and Android forces me to swipe through this huge folder list (I have a hundred or more folders in my inbox –  I use folders to keep my inbox manageable, go figure) rather than just let me use the keyboard (virtual or physical, I don't care) to type the first few characters of the folder name drives me crazy.  These devices are 'supposed' to be Enterprise friendly, but neither Apple nor Google has seemed to view the Enterprise user as one who needs a simple and efficient way to manage filing email messages into folders.\nEven RIM, who hasn't done a lot of smart things lately, was smart enough to still show an option to bring up the keyboard when filing messages – even on touch only devices. How hard can it be?\nAnyway, iOS are cool devices, but unusable for someone who needs to actually manage a real inbox.\nI laughed out loud when I saw an article today entitled Steve Wozniak sings Android praises.\nMy favorite quote from the article? Here ya go:\n“Wozniak conceded that Android is a better choice for people who actually know what they're doing when it comes to technology.”\nThat statement is absolutely correct. I've been having a long, heated argument with some long time colleagues about this topic and it's really true. If you don't know what you're doing or if you don't have any real experience with mobile technology, the iPhone is an amazing device. If you know what you're doing and you have experience with smartphones, the iPhone will drive you crazy.\nI gave my wife an iPad and when her laptop died, I expected her to just use the iPad for everything. No can do – she hates it. She knows what she's doing and knows what she wants to be able to do with the device and since iOS blocks her from doing what she wants in so many ways, the device drives her crazy and she hardly uses it.\nIs this what Apple expected? No, but I imagine they don't really care.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "BlackBerry Status Updates Pane",
  "date":"Tue Jan 10 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1326240000,
  "url":"/posts/2012/blackberry-status-updates-pane/",
  "content":"I'm struggling to find value in the BlackBerry 7 Status Pane that appears at the top of the BlackBerry home screen and, when clicked, displays the screen shown in Figure 1 below.\n\nWhen you look at the image, it should be clear that there's really very little information displayed on the screen. Now, when I wrote about things like this in the past, I got comments back that the issue I'm experiencing is related to my device's current font settings. Those comments were correct, the problem is caused by my font settings. My problem is that I have older eyes and the BlackBerry is the only popular smartphone that allows me to set system-wide font settings. On my BlackBerry devices, I crank up the font size and I can sometimes (if there's bright light) read the screen without my glasses on.\nThat being said though, why do I have to put up with this? The BlackBerry SDK includes an API I can use to determine what the system fonts are, so the OS and an application can tell how the text will display. If I remember correctly, there's even an API an application can use to determine the amount of space a piece of text will take up on the screen (using the current font settings of course). So why doesn't the BlackBerry OS know it needs to render this text onto multiple lines or at least remove some content from each line so at least some of the text will display in its entirety.\nDisplaying small, incomplete parts of the information I'm seeking does me no good. It provides no value at all.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Finished PhoneGap Essentials",
  "date":"Mon Jan 02 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1325548800,
  "url":"/posts/2012/finished-phonegap-essentials/",
  "content":"\nI didn't get a chance to write a formal post about this, but on December 11th I finished the writing process of my forthcoming PhoneGap book called PhoneGap Essentials. I had a contract with the publisher that said I had to deliver the manuscript on February 2nd, but I delivered it about 6 weeks earlier – whew! It was a lot of work and a lot of fun, I really like writing.\nRight now the manuscript is going through a technical review; an experienced PhoneGap developer is reading through the manuscript, testing all the code and making comments back to me. I can't say who it is doing the review right now, but it's someone who really knows PhoneGap, so I'm excited to have him on the review team. So far he's delivered his comments on 19 of the book's 25 chapters, so hopefully he will be done soon.\nI'm going to start working on processing his edits this week and hopefully have the book into the formal editing process some time next week. From there it will take a few weeks to get the editing all done then it's on to production then onto paper. Even though the Amazon page for the book says the book will be available toward the end of May, I expect the book to be in stores by the end of March (or very quickly thereafter).\nDon't forget that you can already pre-order copies of the book now. If you're interested in the book, please pre-order now. Right now, the book's not too high on the search results for Amazon, but as more people order a copy, it should come up in the rankings. Please help me out if you're so inclined.\nOver the holidays I started working on the book's web site at phonegapessentials.com. It's a little light on content right now, but as it gets closer to the book's release date, I'll finish up the articles and post some code samples up there. Check out the site if you get a chance.\nThanks in advance for your help and support.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Another Reason I'm Not Going to Lotusphere",
  "date":"Mon Jan 02 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1325548800,
  "url":"/posts/2012/another-reason-not-going-to-lotusphere/",
  "content":"I wasn't allowed to talk about this until now, but I wanted to share with you another of the reasons I'm not going to Lotusphere this year.\nAs I mentioned in my last post, I've made a lot of friends through Lotusphere and even got myself a wife in the process (a very good wife as a matter of fact). I'd also shared my Lotusphere experiences with several very close friends that I've worked with for many (many, many) years.\nWhen I started my first job out of College at Basicomputer, we were all young geeks and many of us have stayed close over the years. Regarding a few of the guys (like Mike Mantho, Jeff Welch and David Via), we worked together in several jobs over the years. David, Mike and I all got into Lotus Notes at the same time (back in the Notes 2 timeframe) and we attended Lotusphere (with Jeff) together for many, many years. Mike's working at RIM and no longer makes it to Lotusphere. David remained tightly involved with Lotus (being an IBM employee) so I knew I would see him at Lotusphere every year. I might even go so far as to say that hanging out with him was one of my primary reasons for still going to Lotusphere these last few years. David is one of my best friends and hanging out with him at Lotusphere was one of my favorite yearly traditions.\nMike and Jeff have moved on to different things, and this year there's big changes for David as well. Although David Via has been very involved with Notes (now Domino) for so long, time are changing for him as well – he recently left his position at IBM and is joining the team I'm on at AT&amp;T. No more Lotusphere's for either of us most likely.\nDavid wrapped up his job at IBM at the end of the year and starts his new position (working with me again, amazing) at AT&amp;T next week. I can't wait! David took over Ed Brill's old position; I wonder what IBM is going to do with the role now that David has left it. Only time will tell.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Xcode Frustration",
  "date":"Sun Jan 01 2012 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1325462400,
  "url":"/posts/2012/xcode-frustration/",
  "content":"I'm writing an article for the View on how to access Domino data from an iPhone application. My colleague Sunder Somasundaram built the application and I'm doing the write-up. While I know a bit about iOS development, Objective-C is a challenge for me (having grown up with a bunch of different development languages, Objective-C is very different than anything I've worked with in the past).\nI have a Mac Mini I've been using for PhoneGap development and I've been trying for some time to upgrade my instance of Xcode. Unfortunately, Apple has switched to requiring the App Store for Xcode installation and for some bizarre reason the App Store won't install the Xcode update for me.\nI signed up for the Apple iOS developer program, a requirement for access to the latest version of Xcode. When I try to install Xcode from the App Store, it tells me I can't and instead instructs me to use the software update feature to install the update. Unfortunately the software update process doesn't recognize my Xcode installation and therefore won't upgrade it.\nUgh! Why does it have to be so hard?\nI searched around on the Internet and tried different things to make this work. The last thing I tried was to delete the Xcode installer file from the system's Applications folder and that did the trick. Now I'm waiting for the 1.6 GB download to complete – hopefully (no guarantee) the thing will install.\nI hate, I absolutely hate, applications that insist in thinking they're smarter than me. I'm not saying I'm a genius, but when I tell an application to install, I want it to install. Perhaps I know something it doesn't (like there's a corrupt file in the current installation) and I just want the app re-installed. Don't decide for me I shouldn't be doing this, just do it – since I've told you several times that is what I want accomplished.\nI'm not saying Windows is better than Macintosh OS, but at least in many cases, the Windows OS will do things I tell it to do. Not the case with Macintosh OS.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Silly Spammers",
  "date":"Tue Dec 27 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1325030400,
  "url":"/posts/2011/silly-spammers/",
  "content":"I'm kinda fascinated with spam (the email kind, not the tasty breakfast meat). I've had one or more email accounts since the early days of the Internet and it's been fascinating to watch how the spammer industry has adjusted to different efforts by email recipients to thwart them.\nI've recently seen an increase in the number of emails I get (from complete strangers of course) asking me to help them bring some money they've acquired into the US through my bank accounts. What gets me though is that they still keep coming. Do people really, still fall for that? Do people really think someone's going to just give them millions? Are people really that gullible? I think perhaps they are.\nIn the last year, I've received a whole bunch of spam designed to look like the FBI or IRS is trying to give me back some money I'm supposedly owed. I can't believe people fall for those scams either. The FBI doesn't have my email address and I know the IRS isn't emailing me.\nWhat's funny is watching the spammers as they test their spamming software. I received the following email today:\n\nOooh, a Bank of America bill payment was cancelled. I'd better do something about that. Actually, I usually get emails from all sorts of banks – ones I don't have accounts with, so it's easy to tell which ones are spam.  This one happens to 'be' from a bank I actually do business with, so it was worth looking into this one. The first thing I noticed was that even though the message was 'from' Bank of America, it actually came from a Yahoo address. Yep, times must be tough if BofA has switched to using Yahoo for it's corporate email. Right!\nThe next thing I noticed was that there was no body to the email. Interesting. What am I supposed to do here? There's no content in the email. Nice. I guess the spammer forgot to include the actual body of the email message. How then are they going to get me to do something dangerous – like click an innocuous looking link in the email?\nI also love how this particular spammer included a whole bunch of email addresses in the To field. Ya, I'm sure Bank of America's sending out emails to a bunch of people simultaneously about a cancelled bill payment. What, so we all had the same bill payment scheduled?\nAnyway, experience and some common sense makes it really easy to identify spam messages. I know I'm more technical than the everyday person, but how hard is it to tell this is not a valid email? Why do people keep falling for these kinds of things? You'd think by now we'd all be trained on how to avoid scams and spam.\nI used to use Qurb to block spam in my email account. I LOVED it. It was essentially a whitelisting tool – it only allowed messages in that were from people I'd emailed or from contacts defined in my address book. It was a perfect solution and I loved it (I know, I already said that). I'd periodically go into my spam box and unblock legitimate emails (the sender would then automatically become whitelisted) and after 30 days, Qurb would delete everything else). Did I mention I loved that particular solution?\nMany years CA purchased Qurb and changed it to CA AntiSpam. Not much with the product changed, so I was pretty happy with it for a very long time. I renewed my subscription year after year and was very happy with the product. Unfortunately, CA got greedy and decided the bundle their Antivirus with the Antispam solution. You couldn't purchase one without the other. I've always been a big fan of Norton Antivirus, so I had no interest in acquiring a license to CA Antivirus. For a while, I'd renew anyway and just disable the antivirus, but that became tedious and when I upgraded to a 64-bit version of Windows then later upgraded to Windows 7 the solution stopped working for me anyway, so I gave up. I supposedly have a license for the software that's compatible with the 64-bit version of Windows 7 I'm running, but I just can't get it work, so I gave up. Too bad, I really wish I had that product running on this computer.\nI have a 'work' email account I use for business related email correspondence; it's connected with my side business, McNelly SoftWorks. I use Thunderbird for that email account and for years was very careful to not post that email address anywhere where strangers could get to it and send me spam. Something interesting happened recently, and I got on one or more spammer's lists and a good 50% of the email I get to that account is now spam. What happened? Well, I didn't do anything to put my email address on the spam lists (as far as I know), but one of my old customers was regularly getting virus attacks and during one of them, his virus grabbed my email address and gave it to spammers. I started getting a bunch of spam messages from this particular customer, and a few days later, I began getting 50 or so spam messages a day. I'd never thought of that scenario, and I wish I could do something to get off those spam lists. I don't want to change the email address; I've had that one for a v",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "RIM's Depressing Me",
  "date":"Tue Dec 20 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1324425600,
  "url":"/posts/2011/rim-depressing-me/",
  "content":"I was doing some thinking about Research In Motion today. I was sadly disappointed (is that redundant?) when I heard RIM was delaying the release of the new QNX-based devices until late next year. That's a truly boneheaded move after a series of boneheaded moves.\nFirst they announce that future devices will be running QNX. 6 months or so later, they give the new OS a name – BBX, only to find out LATER that that name was already taken. What? Nobody thought to do a trademark search? Apple's pretty pigheaded about that particular topic (Apple was taken by Apple Records when they opened their doors, Macintosh was a very prominent high-end stereo component manufacturer and even one or more of the iNames were infringed upon), but they always seem to get away with it. RIM's failure to recognize the conflict in using BBX was an arrogant, clueless mistake.\nWhen they announced they were changing the name to BB 10, I was surprised. Considering that we're on BlackBerry Device Software 7 right now, making the leap to 10 seemed...misguided. Of course the press grumbled about the name never seeming to get how they probably chose it. BBX becoming BB 10? Of course, converting the Roman numeral X into 10 makes perfect sense. Why are so many other people missing that?\nAnyway, as I tweeted about this the other day, this particular market moves in months, not years. Samsung, Apple, HTC, Motorola and many others release several new phone models a year, often one or more every three months or so. It's a fast moving, dynamic market and RIM just doesn't seem to get it. Announcing a completely new platform then expecting people to wait 18 months or more to see it just doesn't make sense. It's arrogant and clueless. The solution to RIM's problems is to get a smart, new, sexy device platform to market as quickly as possible – no later than early this year (January or February of 2011). RIM's completely capable of doing it, but they just don't seem to be able to actually do it.\nIt's possible that they ran into some issues and that's the cause for the delay. Staking a brand new product line on a series of chips that won't be out until a year after you need them doesn't make sense. If they have the OS, Apps and features locked down, move on and don't wait for that super-duper, special chipset. If you truly believe you can change the market with these new devices, then get it done.\nUgh.\nI'm trying to figure out what's going to happen to them in the next 6 months:\n\nNo new devices till late in the year (they've already announced that)\nUnbearable pressure to get rid of Mike and Jim\nAcquisition?\n\nThey're going to be acquired. So many pundits believe it will be Microsoft, but that makes absolutely no sense. I just can't figure out who'd buy them and why. On top of that, what would be left when the purchase completed? The best and brightest minds are leaving en masse, my former colleagues at RIM are Linking In to me in great numbers lately. RIM is Mike L, but I can't imagine Mike staying after any acquisition, so how great can BlackBerry be with Mike at the design helm? Time will tell.\nI'm not even going to ask if I can attend BlackBerry World and the BlackBerry Developer Conference next year.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Not Going to Lotusphere 2012",
  "date":"Tue Dec 20 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1324425600,
  "url":"/posts/2011/not-going-to-lotusphere-2012/",
  "content":"For the first time in 16 years, I'm not going to be in Orlando for IBM Lotus Lotusphere. I've attended every Lotusphere but one and presented at many of them. It's been a wonderful experience for me and I'm sad for it to end, but I couldn't justify going this year. I hear from others, more and more people are in the same boat as me.\nToo bad. A lot of really great things happened to me at Lotusphere. Let's see:\nI met my wife at Lotusphere. I met her briefly at Sea World at Lotusphere 1999 then connected with her again the following year at Lotusphere. We kissed for the first time at the Copa Banana bar at her company (Interliant) party. Less than nine months later we were engaged and three months after that we were married.\nI was responsible for applications that won two IBM Beacon Awards: 1997 for Biggest Business Impact for an application I helped design for Key Bank and 2001 for Best Tool or Utility for a software package I created which is, I think, still sold today (https://wolcottgroup.com/adt){target=&quot;_blank&quot;}.\n\nI presented a lot of great sessions there (in my humble opinion, of course).\nI met a lot of great people there.\nI made quite a few friends there.\nI drank an awful lot of alcohol there.\nI sat through a lot of keynote sessions – my favorite was John Cleese, my least favorites were the every one in the last five years or so.\nI manned booths there working for three different companies over the years (Realogic, Wolcott Systems Group, and RIM).\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Weinre Debugger and PhoneGap Build",
  "date":"Wed Dec 07 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1323302400,
  "url":"/posts/2011/weinre-debugger-and-phonegap-build/",
  "content":"I'm working on the example application for the last chapter of PhoneGap Essentials. The chapter is about the Storage API and I've build a little mileage tracker (for expense management) application to highlight how to use the different capabilities of the API.\nI got most of the application working but ran into a problem. I was able to create a local database and write to it, but unfortunately the call to the SQL INSERT method returns an error, even though the record is being successfully written to the database. Weird. I can't find anything online that explains why this is happening. Ugh!\nAnyway, I was doing some testing in the Chrome browser and decided to go over to a device to do some testing just to make sure it wasn't Google Chrome giving me the trouble. It wasn't, but I did encounter something that's both fun and interesting.\nPhoneGap includes the Weinre debugger which is a cool application that allows you to debug applications on a device, but watch what's happening in a desktop browser. I've been using it during my work on the book since it makes on-device debugging so much easier. Anyway, I was in Weinre poking around at the application's HTML when I noticed that part of the application screen (on-device) was acting weird. Take a look at the following screen shot:\n\nThe miles input field had some weird stuff around it and I could see the highlight moving to different fields. Turns out that as I highlighted the page elements in the desktop browser, the client-side application highlights the element I was pointing to - in real-time. I expected the device application to update the console on the desktop, but what I wasn't expecting was for the client-side application to also react to what I was doing on the desktop. Way, way cool.\nThe Weinre stuff works, too bad my application isn't.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PhoneGap Beginner's Guide",
  "date":"Sat Nov 26 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1322352000,
  "url":"/posts/2011/phonegap-beginners-guide/",
  "content":"Although there are many books out there that mention PhoneGap or cover the topic lightly, it was nice to see books in the works entirely on PhoneGap. With PhoneGap Beginner's Guide being the first one out the gate, I was excited to receive my copy. Unfortunately I agree with many of the other reviewers on Amazon in that there were a lot of incomprehensible sentences in the book. It's clear that Packt, like with many other of their books, rushed this one out and didn't give it the thorough read it needed.\nThe bigger thing for me was that the book's really not about PhoneGap. Sure, there is a chapter on installing the PhoneGap framework and tools and there are a few chapters on the PhoneGap API's, but the majority of the book covers mobile web development rather than PhoneGap. The majority of the example applications shown in the book were demonstrated in the desktop browser rather than in a native application built using PhoneGap. I understand that you can test some UI stuff in the desktop browser, but PhoneGap has No UI API's - none. So why would you write a PhoneGap book that's mostly about UI? PhoneGap is all about interacting with the device, so as soon as a developer creates their application's UI and starts using the PhoneGap API's, they have to leave the desktop browser and either test in a real PhoneGap application or use RIM's Ripple emulator.\nI did a quick count and there's only about 76 pages on PhoneGap related topics (out of a total of 283 pages – about 25%) while the rest of the book is all about how to do mobile web development. I didn't buy a PhoneGap book to learn about Mustache, XUI or jQuery Mobile – I bought the book to learn more about PhoneGap. I figured since the author worked for Nitobi (the creators of PhoneGap) that I'd learn things I didn't know. Not the case.\nI truly believe this book should have been called Mobile Web Development for PhoneGap Developers – that way the purchaser would at least know that this book is more about mobile web development than it is about PhoneGap.\nNow I'd be remiss if I didn't point out that I'm in the process of completing my own book on PhoneGap called PhoneGap Essentials, so I may be a little biased. One of the things I do while writing Essentials is to assess every topic against the title of the book. I'm regularly trying to pull stuff out of the book because it's not related to PhoneGap. If you read PhoneGap Essentials, you'll find that it's all about PhoneGap, nothing else. Since PhoneGap doesn't have any UI API's, you'll find some pretty horrible UI's in the sample applications I'm including in the book. Everything's focused on how to use the PhoneGap framework and tools and how to use the PhoneGap API's (all of them) in your PhoneGap applications. If you're an experienced PhoneGap developer, don't buy the book – you're only going to be disappointed. If, on the other hand, you're new to PhoneGap and want to know what PhoneGap is all about, then PhoneGap Essentials is the book for you.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PhoneGap Build Android Woes",
  "date":"Tue Nov 22 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1322006400,
  "url":"/posts/2011/phonegap-build-android-woes/",
  "content":"I've been using the heck out of PhoneGap Build these last few weeks as I work through the API chapters in PhoneGap Essentials.\nFor the last three weeks, the process for building BlackBerry applications was broken, it would build an app for you, but it wouldn't include the phonegap.js file, so none of the PhoneGap features in the application would work. They finally fixed it today, but it was broken for about 20 days, and that was painful.\nRecently, I've been focusing on Android development since the BlackBerry stuff was broken. Unfortunately the Android stuff is partially broken as well. You can build an app for Android using PhoneGap Build, but about 70% of the time, the application that's built for you won't install on an Android device.\nIf you take a look at the following figure you'll see an example of what I'm experiencing. The two downloads shown in the figure are for the exact same application. When I build an Android application using PhoneGap Build and it's 3k smaller than I expect it to be, I know it won't install on the device. I just go back to the portal and start the build again. Most of my evenings have been spent repeatedly rebuilding the same app over and over and over again to get one version that will install.\n\nThe problem is that there's no efficient way to communicate build problems to the PhoneGap Build team. There's the help pages that you can link to directly from Build, but people are using that forum for any PhoneGap related question, so there's no easy way to just see what kind of problems are being encountered for Build. People should be using the Google Groups PhoneGap forums for general development stuff and leave the help forum associated with the Build portal for Build related questions.\nAnother problem with that forum is that there's no easy way to see your own posts. Anything I've posted up there is just there and I can't open a page and see my questions and the associated responses. Google Groups is the same way and it's really frustrating. With PhoneGap Build still in beta, there should be a true issue tracking system in use so we can all work together to help make Build better.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Drupal 7",
  "date":"Sun Nov 20 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1321833600,
  "url":"/posts/2011/drupal-7/",
  "content":"I've been using Joomla! for some time now and I've gotten quite comfortable with it. Recently I've been helping August's cub scout pack, a neighbor and close friend build web sites using Joomla! and I've gotten pretty competent with it.\nI branched out a bit and used Concrete 5 for my johnwargobooks.com site. It's pretty cool - it's more of a web based site builder than a true CMS like Joomla and Drupal.\nI've setup domains for my new PhoneGap book, PhoneGap Essentials, and another site I wanted to build. For these two new sites, I've decided to build them using Drupal 7. I'm excited to get started working on the sites; as soon as I finish writing the book (which should be by Christmas) I'll start working up the book's site and let you know when it's up there.\nStay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "PhoneGap Alerts",
  "date":"Sat Nov 19 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1321747200,
  "url":"/posts/2011/phonegap-alerts/",
  "content":"I was working on Chapter 12 of PhoneGap Essentials tonight and I created a quick PhoneGap application to test something I wanted to verify about the JavaScript alert() function. When I tested the application, I noticed something interesting, taking a look at the following code - when I ran the application on an iOS simulator, the Test 2 alert executed before the Test 1 alert.\n\nI know that PhoneGap had finished initializing since the deviceready event fired, but apparently there's something going on that would cause the first alert to queue up and only execute after the second alert, the one using the standard JavaScript alert instead of the PhoneGap alert function, fired.\nInteresting. Not important, but interesting.\nPostscript: OK, I was randomly thinking about something this morning and the solution to this particular item popped into my head. The reason why the PhoneGap alert displays after the JavaScript alert is that the PhoneGap call is asynchronous and the JavaScript alert is a synchronous call. The application passes off the call to display the PhoneGap alert then immediately calls the JavaScript function to display the alert. The JavaScript code executes faster while the PhoneGap code is getting it's work done, the JavaScript code has already fired and is blocking the PhoneGap alert function until the user clicks the OK button.\nYep, it helps when you actually think through things.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PhoneGap Essentials",
  "date":"Tue Nov 15 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1321401600,
  "url":"/posts/2011/phonegap-essentials/",
  "content":"\nLots going on here on the book front. Last week, my publisher and I agreed on a different title for my PhoneGap book. It's going to be called PhoneGap Essentials, and we even finally have a cover for the book as well.\nWe wrapped up the table of contents, a description of the book and my bio last week and it looks like everything got submitted to Amazon because it went on the amazon.com site today for pre-order. You can access the book's page here: PhoneGap Essentials. Please use that link to pre-order the book since I make a little more money that way.\nI'm working my way through the manuscript. I'm 155 pages into the book (out of about 220 total typed pages) and I have about 6 chapters to finish by the end of the year. I'm having a lot of fun writing this book and can't wait to hold it in my hands.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "More PhoneGap Build Problems",
  "date":"Thu Nov 10 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1320969600,
  "url":"/posts/2011/more-phonegap-build-problems/",
  "content":"PhoneGap Build's BlackBerry capabilities have been down for the last two weeks. I've been working through the book's API chapters, writing applications that highlight the capabilities of each and using PhoneGap Build to quickly build an application I can test on multiple devices. It allows me to simply create the index.html file I need, post it up to the server and within minutes (PhoneGap Build is NOT fast) get an application I can deploy to devices for testing.\nThis capability is especially helpful when I was working with the API's related to physical hardware (such as the compass and the accelerometer) since those applications had to run on physical devices and it's much simpler to deploy via the web for testing.\nI first noticed the problem when none of the BlackBerry applications I was working with would fire the deviceready event. After a lot of poking around, I discovered that the problem indicated that the PhoneGap.js file wasn't being included in the BlackBerry application's executable (the .cod file). It would work every once in a while, but 99.9% of the time, PhoneGap Build would build the app, but forget to include the critical phonepap.js file needed to access any of the PhoneGap API's.\nI searched the knowledge base and found another who was having the same problem and even submitted my own tickets on the problem, but as of yesterday it still wasn't working. I know someone from Nitobi is working on it, but I'm not getting any details on the problem or a possible estimate for when it might be fixed.\nI wasn't sure about the value of the PhoneGap Build service when I first started working on the book. It wasn't until I got into working with the apps I needed to write to support my writings that I realized how cool the service is when you're doing this kind of work. It allows you to quickly pen an app by only writing the index.html (and associated files) then gives you apps for multiple platforms without all of the fuss and muss of creating projects for each platform. Now that it's broken, it's making it very hard for me to get my work done.\nHopefully it will be fixed soon, although hope is not a strategy.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "BlackBerry DevCon App on WebWorks",
  "date":"Sun Nov 06 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1320624000,
  "url":"/posts/2011/blackberry-devcon-app-on-webworks/",
  "content":"During BlackBerry DevCon 2011 I did some analysis of the BlackBerry DevCon 2011 mobile application; it was part of my everlasting &quot;What Were They Thinking&quot; series of articles. In the article, I postulated that the application was a BlackBerry WebWorks application which made sense since it's RIM's direction for mobile application development on BlackBerry and because it's a cool and quick way to build mobile applications.\nQuickly after I wrote that article, I was able to validate that it is a WebWorks application. I was working in the application and accidentally selected some of the text on one of the screens (or should I say pages since it's a WebWorks application?) and saw the screen shown in the following figure. Those little blue pointy things shown in the figure are the text selection icons you get when working within the browser.\n\nI wonder if there's a way to turn that off in WebWorks? There should be, but I haven't seen any settings in the config.xml file that would allow that. Something for RIM to consider adding.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "What Were They Thinking 11",
  "date":"Mon Oct 24 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1319500800,
  "url":"/posts/2011/what-were-they-thinking-11/",
  "content":"US Airways is such a technology unsavvy airline. I've been signed up for alerts for a long time now, but they just refuse to alert me when it's time to check in for example. Their day of travel alerts are next to useless as well (see Figure 1). They're notifying me that my flight is expected to be on time, but they refuse to tell me what gate the flight is scheduled to depart from.\n\nFigure 1\nIf I already have my boarding pass (which I did) and I'm heading to the airport, many airlines leave out of multiple terminals, so how am I supposed to know which terminal I'm supposed to be dropped off at?\nCharlotte has 4 terminals where US Air flights come in and out of. For my morning flight, I'd already checked in and didn't have a bag to check, so I just walked into the airport and headed through security. Once I got inside, I started looking for my gate and of course the first location I went to, all of the screens were blank. With 4 terminals as viable options for me, I was in a pickle – fortunately I was able to find a bank of monitors that worked and quickly learned my flight was leaving out of a faraway terminal, but if US Air cared enough about me, they would have told me before I got to the airport which terminal I needed to go to. I understand that the gate might change, but why not tell at least what you know today then let me know, via another email, if the gate does change down the line?\nThis truly makes no sense to me – you have the data, I'm your customer and you know I'm interested in the data, why not share it with me?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "BlackBerry Development Tool Macintosh Installation Weirdness",
  "date":"Thu Oct 20 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1319155200,
  "url":"/posts/2011/blackberry-development-tool-macintosh-installation-weirdness/",
  "content":"I was excited to learn at BlackBerry DevCon 2011 that RIM had finally released the Macintosh versions of their development tools for BlackBerry and Playbook development. Having a MacBook in my hotel room (my Windows Laptop died ore than a week ago) I downloaded the code and tried to install it. I noticed some weirdness with the tool installation, so I thought I'd write about my experiences here.\nThe tools download as a zip file, a different zip file for BlackBerry vs. Playbook development. That's not that big of a deal, except the zip files contain an application installer with EXACTLY the same name. Instead of naming the packager within each zip file with a name appropriate for the particular installer, they named them both the same and it causes problems. Take a look at Figure 1, you'll see the two zip files (with separate file names) but then two applications, both with the same name (although the second one has a 2 after it's file name).\n\nFigure 1\nHow do you tell which one is which? You can tell by the file sizes (very different between BlackBerry and Playbook), but you shouldn't have to – especially since the Macintosh Finder doesn't render files in this layout by default. RIM should have thought of this scenario and named the installers better.\nOK, when I got around to installing the tools, I came across something I'd never seen before on a Macintosh. Take a look at Figure 2, it shows the first screen you see when installing the tools. When I first saw this message, I had absolutely no idea what to do with the information. I knew that Windows would allow me to run an installer as an Administrator, but had no idea how to do that on a Macintosh.\n\nFigure 2\nI closed the installer and poked around to see if I could figure out how to run the application as an Administrator. I couldn't find anything, so I just launched the installer again. I stared at the screen for a while then decided that the only option available to me was to click the lock icon and see what happened.\nGuess what? It prompted me for the Administrator's (me) password as shown in Figure 3 and proceeded to perform the installation.\n\nFigure 3\nWhat concerns me though is why I had to go through that? Why didn't the install just progress and leverage the feature of the Macintosh that prompts me for the password? That stupid little lock icon didn't make sense, nor did the prompt that apparently was trying to tell me that I needed to click the lock icon to get past this particular issue.\nI've said this before, if there's only one option available to me, why not just click it for me automatically? Why make me click it when there's really nothing else I can do? Why doesn't the installer provide a message that tells me I need an Administrator password then politely let me know I can enter said password by clicking the lock icon? There was absolutely no way for me to know, based upon the information provided me, that the lock icon allowed me to enter the Administrator password. Why put the lock icon, the only thing I can and should click as far away as possible from the message warning me that I needed to click the icon?\nIt's almost like they really don't want me to install the tools. Ugh!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry DevCon 2011 Days 2 and 3",
  "date":"Thu Oct 20 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1319155200,
  "url":"/posts/2011/blackberry-devcon-2011-days-2-and-3/",
  "content":"Today wraps up BlackBerry DevCon 2011. Overall it was a great conference. Like I said in a previous post, the sessions and the pace were great. There wasn't a lot of energy about the place, but it was a big crowd and lots of focus on web development and open source tools.\nThe one disappointment for me was a session I attended this morning on PhoneGap and BlackBerry WebWorks. I was really looking forward to the content, but the presenter was interrupted with so many general questions about PhoneGap (rather than questions related to the session's content) that he ran out of time and only covered about half of his presentation. I wish he'd enforced only taking questions at the end of the session and gave me what I was looking for from the session. Oh well. What RIM should have done was have an intro to PhoneGap session first, which would have allowed this more advanced session to cover its content as planned.\nI learned a lot about many open source JavaScript libraries – as soon as I wrap up the book I plan on digging more into those libraries just to round out my skills.\nNot sure if I'll be attending another DevCon. My employer has been great in letting me attend and the information I gather helps me in my day to day job, but the event is really more about game development anymore so there's not much there for me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "What Were They Thinking 10",
  "date":"Wed Oct 19 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1319068800,
  "url":"/posts/2011/what-were-they-thinking-10/",
  "content":"In preparation for BlackBerry DevCon 2011, RIM released this year's version of the DevCon mobile application. I've written here about this application and the BlackBerry World (WES) conference applications over the years and I've never been quite happy with the applications. I've always felt that the applications were hard to use and included features that just weren't needed in an application like this. My belief was that RIM focused too much on making a flashy, showcase application instead of focusing in an application that got the job done as efficiently as possible.\nThis year's BlackBerry World and DevCon applications were different. They are highly useful, efficient and got the job done. Gone were the fancy background graphics that made the menus difficult to read and gone too were those ridiculous page transitions that took so much time to get you from one screen to another. This year's DevCon application just works and I found myself actually using it for a change rather than using the desktop web version and downloading session information into my calendar.\nIt looks and feels like the application is a BlackBerry WebWorks application. It shouldn't be possible to tell, but for some reason I just 'know' it's a WebWorks application. The cool thing is that because it's a WebWorks application, it was very easy for RIM to make it available for both BlackBerry and Playbook devices. That's a great testament to the application direction RIM has taken.\nThere were some problems with the application though, and that's why this particular post made it into the What Were They Thinking category. In this case though, I'm really not trying to complain here (as I usually do with this particular series), but instead to point out design or implementation decisions that were made that probably should have been made differently.\nLet me show you what I mean:\nWhen looking at the application home screen shown in Figure 1, it's really hard to tell that the icons shown there are clickable. They look like they're disabled. They use color for the logout button and the DevCon logo, but deliberately didn't use color to indicate clickable areas on the home screen. Those icons are dull and truly (to me) do not look like anything I should be able to click on.\n\nFigure 1\nAs you will see later, other parts of the application are rich with color, but not the home screen icons. What were they thinking?\nA neat new feature for this year's application was the ability to synchronize your event schedule with your BlackBerry calendar. Finally! For previous conferences, you could do your calendar on the desktop web and download them into a calendar program (Microsoft Outlook, IBM Lotus Notes and so on), but it was challenging to do it from the mobile application. With this year's application, synchronization is automatic and it's an excellent feature.\nOne thing I noticed though, and I probably wouldn't have noticed it except that it caused me a problem, was that the calendar appointments the application made for me were not marked as Busy on my calendar. One of the reasons I liked the calendar sync was that it updated my calendar so colleagues would see that I'm busy and not schedule appointments for me during those time slots. I had people trying to schedule me for meetings in time slots I knew I had blocked for sessions I was attending. It was only when I looked at some of the entries created by the program that I realized that even though the DevCon app made the appointments for me, it simply didn't make them the right way. What's the point of putting an item in my calendar but not marking my time as busy for that time slot? What were they thinking?\nAnother thing I noticed, and this is a HUGE pet peeve for me, is that when you open the agenda or my schedule, the application doesn't by default open the current day's schedule. The application knows what day it is and it knows I'm opening my schedule, why not default to opening the current day's schedule then give me options to select different days if I want? The designer of the application has to think about how the application will be used; in this case they didn't. 99% of the time I'm going to be looking at my current day's calendar, why not show it to me first instead of making me click the current day every single time I open that part of the application. I shouldn't have to make a selection on the screen shown in Figure 2 every single time I open that part of the application.\n\nFigure 2\nOpen the current day's schedule no matter what then give me previous day and next day buttons on the top to use to get to a different day. It's only a three day conference, so it would never take more than two clicks to get to any day but only one click to get to the current day.\nAnother thing I noticed about Figure 2 is that it's impossible to tell that the BlackBerry Partner Directory image at the bottom of the page is a clickable item. I noticed by accident that it was there and clicked on it to see if i",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "BlackBerry DevCon Day 1",
  "date":"Tue Oct 18 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1318982400,
  "url":"/posts/2011/blackberry-devcon-day-1/",
  "content":"Well, Day of BlackBerry DevCon 2011 has wrapped up and it's been a pretty interesting day.\nIt started with RIM moving the start time of the opening session to 8:30 AM then delaying the start until 8:50 AM. I showed up later than I wanted to, about 8:20, and there was a huge line of people waiting to get in. Fortunately for me, I didn't have to wait long and was quickly let in. Being a DevCon Alumnus allowed me to use the line jumper queue and get in right away.\nIt makes no sense to me – why move the start time up then NOT start the event. I had a meeting at 11, so I knew I would be leaving early and the earlier start time would have allowed me to miss less of the event. It makes no sense to me why you'd delay like that. No announcements were made; nobody knew what was going on until they finally let us in right when it was supposed to be starting.\nThen, as we sat there waiting, and waiting and waiting, they made announcements letting us know the keynote would be starting in 5 minutes, then 1 minute. Unfortunately, they made those announcements repeatedly during the 20 minutes I sat waiting. It's not right and it's disrespectful of my time.\nNot much in the way of special announcements. Mike L. started with apologizing for the outages the previous week then announced the new platform would be called BBX. Nothing about features. Nothing about release timeframes. Nothing about the future BlackBerry devices that would be running the OS. Only an announcement about what it would be called and nothing else. Many people have emailed me asking about the mood at the event and how people were reacting to the BBX announcement and so far nobody has anything to really react to. All we know is what it's going to be called, nothing else – so it's no surprise that people are not that excited.\nWe did get free Playbook devices – which is really cool. They provided us with an option to receive a device with the standard version of the OS or a device running a beta version of the OS. I'd tell you which version I selected, but it would be a violation of the beta agreement they required anyone who took a beta device to sign for me to tell you which one I selected. I now have two playbook devices, I'll unpack the new one and play with it's updated OS when I get home. Unfortunately I'm unable to write about my experiences.\nThey did announce new versions of some of the developer tools and even released Macintosh versions of them (which is pretty cool). I've been using a Macintosh for my development work for the PhoneGap book I'm writing and my work laptop died last week, so I had to switch to my MacBook for a while. I'm trying to decide whether I want to make the switch permanent. I'll write about some 'interesting' installation problems soon.\nWith no fanfare or real introduction as to who this guy was, the Mike Kirkup replacement took the stage and announced all sorts of interesting (and welcome) changes to the BlackBerry developer web site. Everything's been renamed around the BlackBerry Jam concept and it really makes no sense to me. It's flashy and cool, but it's at the same time lame and unprofessional. They did announce that RIM would no longer require a login to download the developer tools, which is a long overdue change. That makes downloading tools less challenging (what was that password again?) since RIM required capital letters and alternate characters such as dashes and numbers for your password (which was way, way overkill for simply downloading free developer tools).\nThe keynote was mostly about Game developers and that's no real change from last year. In today's cross platform world for Enterprises, it makes sense that RIM would focus on the developers that matter the most to them: game developers.\nVery little was said about Java development and there are very few sessions here about Java development tools. It's clear that WebWorks is working for RIM and RIM's developers, so no real loss there. What will happen is that native Java development will only be needed for device driver or very high performance game development going forward.\nThe afternoon was filled with attending sessions. This year the sessions have been interesting. I've enjoyed most of them although very few of them have had the technical depth I wanted them to have. Still, the sessions have been very interesting. Open source tools are more prevalent this year. I've attended sessions on JQuery and Dojo, and there have been sessions by Sencha (I think ) and one on PhoneGap I'm attending tomorrow.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "PhoneGap Build Woes",
  "date":"Tue Oct 11 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1318377600,
  "url":"/posts/2011/phonegap-build-woes/",
  "content":"I was planning on being about halfway through the book by the end of last week, but my travel schedule and several very full weekends have kept me from reaching that goal. I'm this close to finishing the chapter on PhoneGap Build, but I'm really making very little progress no matter how much work I put into it.\n\nThe problem I'm having is that the PhoneGap Build service is working out to be very unstable. Granted I have been working with an Alpha version of the service which only recently switched to Beta status, but as I'm working through the examples for the chapter, once I fix one problem, another pops up.  First there was a problem with dashes in JavaScript file names on BlackBerry, which doesn't affect RIM's tools, but seems to intermittently affect PhoneGap Build. Next came an issue with the iOS signing process – which is something I've not worked much with and was happy to finally figure out. Now that I finally have an installable iOS application, the PhoneGap Build service now consistently times-out when building the BlackBerry version of the application.\nAll I want is a complete build, something that shows my test application built for every supported OS, but I just can't seem to get there. That's all I need before I write about debug mode then I can put this chapter to rest.\nMy goal is to finish this (hopefully) today then spend the rest of the week doing the Windows Phone chapter. That will put me solidly halfway done and I can spend the rest of the year working on the chapters on the PhoneGap API's. Wish me luck!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Adobe PhoneGap",
  "date":"Tue Oct 04 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1317772800,
  "url":"/posts/2011/adobe-phonegap/",
  "content":"Of course things got kinda interesting this week with the PhoneGap project announcing that they're moving over to the Apache Project and changing their name. Originally slated to be called Apache DeviceReady, there's already a name conflict so the newer option looks to be Apache Callback. Ugh. We'll see what new names appear today.\nNext came an announcement from Adobe that they're buying Nitobi, the company that founded and is managing the PhoneGap project. This is a very interesting development and I'll continue to watch things as they unfold. What's interesting for me is that as a part of Adobe, the folks at Nitobi are going to be able to focus entirely on PhoneGap development rather than on generating revenue. I imagine things will only get better with this arrangement.\nOnce I'm done with the new PhoneGap book, I'll be half-way done by the end of the week (hopefully), I'll start looking for some ways to contribute to the project. They need SO MUCH help with documentation.  Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Macintosh OS Developer Friendly Tools",
  "date":"Sat Sep 10 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1315699200,
  "url":"/posts/2011/macintosh-os-developer-friendly-tools/",
  "content":"As I work through the chapters of my forthcoming book on PhoneGap, I'm working on both a Macintosh and PC which reminds me of first years of my professional career. I was doing PC support for a PC dealer called Basicomputer and always had a IBM PC and a Macintosh on my desk plus even had an Apple II for a long time as well (it was an Apple IIgs).\nAnyway, as I'm writing about installing the PhoneGap software for Android and iOS development I found myself in need of installing Ant and Java on my Macintosh. As I poked and prodded around on the Internet I was struggling to find the information I needed about installing those two tools on Mac OS. It was really frustrating and I couldn't figure out why nobody had written about the topic when I discovered by accident that the Macintosh installs Ant and Java by default. Nice!\nOn my new Mac Mini running OS X Lion, Java isn't installed, but installs itself when you first try to run a Java application. That's pretty cool. Ant's installed and even on my Macbook (running snow leopard) the latest version is on there already.\nOf course, all those long time Mac users (I used to be one, but switched to PC a long time ago – I may switch back) already know this, but why would they not write documentation applicable for people first picking up a Macintosh? The difference between my writing and the writing of others is that I try very hard to assume VERY LITTLE. I wish others would do the same.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "A New RESTful Service",
  "date":"Tue Sep 06 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1315353600,
  "url":"/posts/2011/a-new-restful-service/",
  "content":"I have published several articles on this site that illustrated different types of web services for Domino that I have used in some mobile applications. Domino easily supports XML-based web services and platforms such as BlackBerry and Windows Mobile have inherent capabilities that allow applications to consume XML-based web services. Other platforms on the other hand don't have built-in support for XML-based web services, so I've had to implement RESTful services for applications built for other platforms such as Android and iOS. More recently I've decided to make a change to the RESTful agent I've been using for my applications and thought I'd document the changes here.\nWith my original web services, the idea was that a mobile application would send a request for a list of contacts that matched a search string then, when an application user selected a user, the application would make another call to the server to obtain the details for the selected contact. This process is illustrated in Figure 1.\n\nFigure 1 – Two-part Request Process\nWhen I first started doing mobile development, performance was important. The networks were slow and mobile devices had limited processing power, memory and battery life. In order to make the most efficient use of the network and increase performance and battery life for the device, I built the services to make the best use of network and processing power. What this meant was that the services would be designed to send a little data as possible over the wireless network and to ensure that data that would possibly not be used by the mobile application wouldn't be sent across the wireless network.\nSo, in my design, I deliberately built the services so the first request simply retrieved a list of contacts that matched the search string then allowed the application to get detailed contact information only after they determined which contact they were interested in.\nIt seemed like a good approach and has served me rather well. The problem with this approach though is that it makes building the mobile application more difficult. There are two calls to the server and the results have to be parsed twice as well. If the mobile user selects one contact, then decides it's the wrong one and switches to another, there's another trip to the server for more data.\nIt's efficient on the network, but inefficient within the application. The thing is, mobile users and mobile device manufacturers stopped caring about network usage and battery life a long time ago. Users want whatever they want and they want it now.\nApple's Dashcode IDE has some pretty cool features that make it easy to work with remote data sets. When you build a Browser project using one of Dashcode's wizards, the application expects a list of records and the details behind the list to all be delivered to the application at one time. The result is only one trip to the server, and a better user experience. There's only one trip forth and back from the server which makes the user feel better, but we're delivering data to the mobile device application that the user may never look at. Oh well.\nSo, I decided to rewrite my Domino Directory lookup agent so all of the relevant data could be retrieved with a single call to the RESTful agent as shown in Figure 2.\n\nFigure 2 – Single Part Request Process\nWith this new service, a single call is made to the server using the following URL:\n\nwhere SEARCH_STRING represents the first three characters (or so) of the contact name the user will be searching for. As an example, a call to the server using the following URL:\n\nwould return the following JSON data (or something like it):\n\nThe JSON text returned from the server in this case is an array of JavaScript objects. If you expand the JSON text to show the structure of the data, the data will look like the following:\n\nI can use this data in my application by only pulling out the list of FullName values when presenting a list of contacts, then digging in and displaying the contact details only after a contact has been selected within the application.\nThe brackets (the [ and ] characters) are used to define an array and the curly braces ( the '{' and '}' characters) are used to define a JavaScript object. So, what you're seeing is a essentially a two element array, where each element is a complete JavaScript object describing contact details for a user defined in the Domino Directory database.\nTo obtain this output, all you need is a simple agent in a Domino Directory database. To create the RESTful service, create a new agent in your Domino Directory and set the agent properties shown in Figure 3. The agent is a web agent; it is triggered by a URL request triggered by the mobile application (or web browser). It uses an 'On Event' trigger and the event is defined as 'Agent list selection.'\n\nFigure 3 – Domino RESTful Agent Properties\nMost of the agent's work is done in the Initialize subroutine which performs the following steps:\n1. Parse the incomin",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "RIM Update",
  "date":"Tue Aug 30 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1314748800,
  "url":"/posts/2011/rim-update/",
  "content":"Research In Motion made some interesting announcements yesterday.\nFirst of all they announced that they've FINALLY launched a private beta for native development tools for the PlayBook. With the device announced more than a year ago and physical devices in the hands of users since May, you'd think a native SDK would have been made available a long time ago, but you'd be wrong.\nHere's the announcement: https://devblog.blackberry.com/2011/08/native-sdk-for-blackberry-tablet-os-closed-beta/.\nGoogle and Apple typically make their SDK's available at device announcement or at least at device release, but Research In Motion has always been slower to market with their development tools. Now, in their defense, they had development tools for PlayBook available at device launch, both WebWorks and Adobe Air development options were available. So not having a native SDK wasn't a big deal, but any game developer or someone building device drivers would suffer until now. It's a closed beta, so that means public beta and final release are months away.\nMy only hope is that they can get this figured out before the new QNX-based devices become available supposedly next year.\nThe second announcement was from Mike Kirkup, Research In Motion's long standing director of their Global Developer Relations team. Mike Announced on https://mikekirkup.com that he was resigning from his position at Research In Motion after 10 years with the company. This isn't good news and it will be interesting to see who replaces him or what happens with the position. Mike's team worked with all Research In Motion development partners, helping them bring commercial software products to market. I'm assuming they'll continue with their work, but I wonder if Mike leaving is related to some fundamental change to how they will support developers and that's why he's leaving.\nOn (or about, I can't remember) July 25th, Research In Motion made a huge reduction in it's workforce. The biggest impact I'm aware of was to the US Carrier business units. When I worked at Research In Motion, I was part of the team supporting AT&amp;T. With the reduction in force (RIF), RIM whacked from the AT&amp;T business unit the entire Regional Technical Manager (RTM) team except for one person and as I understand it, cut the Regional Sales Team (RSM) in half. So, what was once a team of between 16 to 20 people is now a team of 5 people. Ouch.\nWhat's next I wonder?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Native SDK for BlackBerry Tablet OS",
  "date":"Tue Aug 30 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1314748800,
  "url":"/posts/2011/native-sdk-for-blackberry-tablet-os/",
  "content":"This could be fun!\n\nRIM announced today private beta for the Native SDK for BlackBerry Tablet OS. You can read the announcement here.\nI've kinda gotten away from BlackBerry development, focusing more on cross platform development tools, so I've not really kept up with what RIM's doing with the PlayBook. The WebWorks stuff is…interesting and Hybrid frameworks like WebWorks is where the market is going (the popularity of the PhoneGap and Titanium frameworks has helped prove that one) but there always seemed to me that there would remain the need to write native applications for any device. I couldn't understand how RIM could be using native development tools to write applications for QNX and more than a year after they announced the device didn't have any native tools available. I know they expected that these tools would only be needed for high performance applications such as games and specialty drivers, but sometimes you just want to kick around in the API's directly.\nBy why so late?\nThis is something Google and Apple have definitely done right and RIM seems to completely ignore. When Apple or Google announce an OS upgrade, they release the appropriate SDK's with the device or even sometimes earlier. RIM on the other hand, doesn't seem to understand the need to have timely access to the newest development tools. I don't remember whether it was BlackBerry Device Software 4.6 or 5.0, but I remember that for one of them the native development tools were still in beta almost 6 months after the release of the device running the software. Seriously? C'mon – how hard can it be? You've released the device, how hard can it be to release the tools you used to actually create the applications running on the devices people are holding in their hands?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "RAID 5 Pain",
  "date":"Mon Aug 22 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1314057600,
  "url":"/posts/2011/raid-5-pain/",
  "content":"At the beginning of the year, I replaced my main PC in my home office. I'd had the last one for more than 4 years and it was really time to get rid of it. When I build a new PC, I always go for the biggest and fastest and this one was really fast 4 years ago, but could no longer keep up.\nFor the new one, I purchased an Intel i7 quad core, dual graphics cards, 24 GB of memory and a big honking 8 TB drive array configured for RAID 5 (giving me 6 TB of available space). For my boot drive, I implemented a solid state drive, very cool but I wish it was bigger (Isn't that always the case?). I'd previously used AMD processors, but for this one, I knew I'd be doing a lot of work in Virtual Machines so I wanted the hyper threading capabilities of the i7 processor.\nIt wasn't long after I had this beast up and running that the RAID controller indicated that the third drive in the array was indicating that it was experiencing SMART errors. Soon afterwards the 4th drive failed completely. I quickly ordered a replacement drive from newegg.com (I LOVE those guys) and, when it arrived, replaced the failed drive in the array.\nI then downloaded the drive diagnostics utility from the Samsung web site (I was using 4, 2 TB Samsung SATA drives for my array) and plugged the drive into one of the test machines in my lab. Quick tests indicated that there was an error with the drive (I already knew that). Surface test indicated that there was a problem with the drive (I still already knew that). After low level formatting the drive, I reran the tests and was informed that the drive was bad (didn't I already know that?).\nI opened the manual that came with the drive and saw that I was supposed to call an 800 number to get support. I called the number and after only getting transferred once, spoke with a tech who gave me directions to go to a web site to generate an RMA number. I would have completely avoided the phone call if they would have just given me the support URL in the manual, but apparently that's not the way it works.\nI shipped the drive off to Samsung and soon received the replacement drive. I installed the new replacement drive in the drive 3 slot in my RAID array and of course now I'm completing the same steps for the other failed drive. So far, the quick test and surface test have completed and I'm currently low level formatting the drive. Since this drive didn't actually fail, only threw some SMART errors, I'm not sure what's going to happen here. I'd prefer to have the drive replaced and have a good backup drive lying around to use when the next drive goes bad.\nI'm disappointed that I had the drive failures, but I am glad I implemented a RAID Array (so I could easily recover from a failure). What bothers me most is that I have to pay shipping three times to get these two drives replaced under warrantee (one for shipping of the purchased replacement drive and two to send drives back to Samsung). Even though these drives are under warranty, I have to incur a cost to use the warranty. Sucks, but it's better than the alternatives.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Can't Speak at BlackBerry DevCon",
  "date":"Thu Aug 11 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1313107200,
  "url":"/posts/2011/cannot-speak-at-blackberry-devcon/",
  "content":"I got my 'thanks but we don't need you to speak at the BlackBerry Developer Conference' email this week. I'm really frustrated; I've been silent on this for years now, but I have to say something now. Here we go, but be sure to keep in mind that the opinions provided here are mine alone and do not reflect the opinion or public statements of my employer.\nI've attended every BlackBerry Developer Conference. One as an employee of Research In Motion, another as an employee of BoxTone and two as an employee of AT&amp;T. As you may or may not know, after I left Research In Motion, I wrote one of the first books dedicated to BlackBerry development (I usually say mine was the first, Anthony Rizk's Beginning BlackBerry Development technically made it onto paper a week before mine, but my book, *BlackBerry Development Fundamentals was available online on Safari Books Online months before that).\nWhen I was at Research In Motion, I couldn't present at the conference because I didn't work in the ISV Alliances team nor did I work on any of the internal BlackBerry development teams. I worked for one of the carrier business units (AT&amp;T of course) and even though I was considered expert enough to work with customers on BlackBerry development stuff, I wasn't good enough to speak at the conference.\nThe next year, I submitted a couple of session topics but was declined. The following year, folks at Research In Motion actually encouraged me to submit session abstracts, but turned me down anyway. By then, there were two books on BlackBerry development on the market and I'd written one of them (the author of the third book doesn't even attend the conference). You'd think I would be qualified to speak at the BlackBerry developer conference, but nope – declined. I didn't submit any topics last year, but I just knew it was an exercise in futility. This year, just like Charlie Brown trying to kick a football being held by Lucy van Pelt, I thought I'd try yet again – declined.\nThe issue for me is that Research In Motion is just too close to some of these topics to present them with any type of real impact. Watching Tariq Tahir year after year present on Push and completely omit important details plus get interrupted time and time again with questions because his presentation wasn't structured well - was painful. Watching Adam Stanley and Tim Neil present on Widgets (WebWorks) at last year's conference and get peppered with questions over and over again because they just weren't explaining the details clearly was painful as well.  Developer types at Research In Motion do know their topics, but many are too close to the topics (and therefore omit important, assumed details) and don't really have the organization and presentation skills needed to impart the information well.\nDeveloper Conference sessions should be stuffed full of details, examples and background information. It should be structured in a way optimized for people that don't know anything about the topic. Research In Motion developers assume too much when they present topics, they assume you know a whole bunch of background information, rather than build their sessions with no assumptions and therefore making a bigger impact on less knowledgeable learners.\nLet me give you an example. When I was working on the book, one of the chapters dealt with issues with the browser related to problems that occur since JavaScript was turned off by default in the BlackBerry browser. One of the Research In Motion reviewers, made a note indicating that it could easily be turned on programmatically but provided no additional information. I searched everywhere on the Internet looking for any reference to how this could be done and found nothing. Finally after begging for the solution, Research In Motion gave me a quick sentence on how to do it.  I worked away at it, with no additional support from Research In Motion and finally figured it out. It's documented on this site and as far as I can tell, for a very long time (possibly still) it's the only reference on the Internet that explains how to do it. The reviewer from RIM just assumed I'd understand the comment, even though the information being referenced was NOT explained or documented ANYWHERE.\nI've always wanted to present on BlackBerry Push capabilities. For the longest time, it wasn't documented very well anywhere within Research In Motion's documentation, and I felt that I knew more about the topic than most people outside of RIM . I wrote more than 100 pages on push in BlackBerry Development Fundamentals and I think I know it pretty well. If you're a developer and you want to learn it, there's on-device API's that help you leverage it, but for creating server processes that leverage push, the only examples available from RIM help only if you're using Java on the back-end. If you take a look at Research In Motion's last documentation on RIM Push available here you'll find that the sample application illustrating PAP shown beginnin",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "What Were They Thinking 9 (RIM Again)",
  "date":"Tue Jul 12 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1310515200,
  "url":"/posts/2011/what-were-they-thinking-9-rim-again/",
  "content":"For a long time now, I've been running a series on mobile applications, highlighting where developers build an application for a mobile device without really paying attention to the mobile device or the needs of the mobile user.  In this article, I'm going to shift gears and talk about something related to mobile, but not directly to mobile applications. I've written about this company many times before, let's take a look…\nI received the following email this morning from Research In Motion. I'd signed up for updates, so they would notify me when new software was available for my device.  I thought it was a good idea to keep my BlackBerry device up to date and it was great to receive the notification.\n\nFigure 1\nWhat struck me as odd was not that the image they'd included in the email didn't load, but instead that they included a note at the top of the message saying:\n“For best results, please view this message from your desktop computer.”\nSeriously? An email from Research In Motion with a suggestion that the email would look better on a desktop computer than on a BlackBerry? That makes absolutely no sense. I have a BlackBerry. They know with a pretty high level of certainty that I have a BlackBerry (since I signed up for BlackBerry software update notifications, didn't I?). This makes absolutely no sense whatsoever.\nWhat they did was format the message so it had a nice layout when opened in the desktop email client. It was designed to center the message's content in the center of the available space in the email client. Big deal, what's the point? I don't need emails content such as this centered in the email. It's a simple message letting me know that there's a software update for my BlackBerry device, does it really matter what it looks like?  All they did was make it so the message was larger than it needed to be (all of that HTML content used to make the message formatter better on the screen), took longer to download than necessary and costs the receiving company (my employer) additional cost (over text-only messages) to store and forward the message to me.\nHere's what the message looked like on my BlackBerry:\n\nFigure 2\nYes, I have my fonts cranked up (I'm old), so it's bigger that it would be on your device.  The image at the top of the message doesn't appear on my BlackBerry device either, so I'm not sure what's going on there.\nWhat I needed was a simple, text-based email from Research In Motion letting me know there was new software available for my BlackBerry device. I needed to know it was available, how to load it and what is different in the new version (what's new, what's been fixed).  I didn't get that. What were they thinking?\nWe need to get back to simple. Use HTML formatted email where it matters – not in simple emails like this. If you know the reader is likely to be reading the email on a smartphone, format the message so it looks OK in both the desktop and smartphone email clients. A message to a BlackBerry user with information about his or her BlackBerry device should be formatted expecting that the message will be opened on a BlackBerry. It makes no sense to do anything else.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "On the Open Letter to RIM",
  "date":"Thu Jun 30 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1309478400,
  "url":"/posts/2011/on-the-open-letter-to-rim/",
  "content":"I don't know if you heard about it or not, but a RIM executive published an open letter to his bosses: Mike L and Jim B of RIM. It's an interesting read and it had to be said. It's really sad, but RIM has been slow in its response to market changes and it's likely that they won't be able to recover.\n\nTheir development tools are sub-par and it takes a ridiculous amount of time to release them. Where Apple and Android pre-release their development tools or at least ship them on the same day the device is announced, RIM does prolonged betas and in one case delivered the SDK out of beta only after a device that used the particular SDK had been in market for almost 6 months. Ridiculous.\nI was trying to get my demo machine ready for a presentation at The View Developer Conference last week and had upgraded one of my BlackBerry Java projects that I was going to show at the conference. When I loaded the project, Eclipse gave me all sorts of errors that I just couldn't resolve. I quickly called a former colleague at RIM and he informed me that he never imports old projects into Eclipse; he created a new project every time and copied his code over into the project.  Ugh! Is that world class development? No ! Is it at least acceptable? No way!\nIs Apple's Platform better? No, absolutely not. I wrote about this a few weeks ago, but developing for the iPhone is much, much harder than it is for any other mobile platform I've worked with (I've worked with a lot). In a previous article on this site, I referred to a post by an Australian developer who confirmed my conclusion.\nRIM gets hammered because its technology is so old, but the iOS tools are even older. BlackBerry development's primary language is Java which was released in 1995. NextStep, the stuff that Objective-C (and all iOS development) is based on was released in 1989. iOS has no Garbage collection capabilities, the developer has to manage the lifecycle of all objects – there's not another popular smartphone platform in market that has that same limitation. In Objective-C, all references to variables are through pointers – that's so 1980's (or so Pascal), the development world is way past that approach. Compared to every other modern development language, Objective-C code has so many quirks that it's essentially unreadable (to me anyway – and I've been a professional developer for almost 30 years).\nIf you're a new developer, Objective-C might make sense, but it you've been working with many different development technologies, you'll find it almost incomprehensible. There's no reason it has to be so hard, but it is.\nRIM's problem is that it's old. RIM has done a very good job of forcing their internal development teams to continue to support older devices as new ones (with new capabilities) are released. That's a good thing, backwards compatibility is very important. Unfortunately that does make it harder on developers – there's no getting away from it and it's the kind of thing that Windows developers, Linux developers and many other platform developers live with on a day to day basis.\niOS is new, Apple is going to have the same problem in the future. They've already started releasing newer devices with higher screen resolutions, so developers now have to deal with two iPhone screen resolutions plus the iPad. As displays get better or form factors change, it won't be long before Apple developers start complaining about all of the different devices they have to code (or create graphics) for. When apple starts adding additional interfaces (neural and who know what else) the same problem will occur. It's the way software development works and it has nothing to do with Apple or RIM. For Apple, forcing users off older OS helps eliminate some of those problems. Since users are essentially forced to upgrade as soon as a new version of iOS is released, developers don't actually have to support older OS's for that long. Unfortunately, RIM works with enterprises and that's just not acceptable for most companies.\nI said a long time ago that RIM should abandon their older devices and release a new, more modern way of building mobile applications. They've done that now with their acquisition of QNX, but I agree with the market that this transition has taken too long. Working for a carrier, I understand the pressures RIM and other device manufacturers face, but it is taking them way, way too long to get things done. They announced the PlayBook when they weren't ready, they released when they were not ready, those aren't smart things to do. Releasing the PlayBook without native email support is incomprehensible.\nI truly do not know whether it's too late for RIM or not. I feel for them and hurt a little inside when I see their repeated stumbles. There's a whole bunch of smart people there, so there's a chance they'll pull it out, but it will take very drastic measures and a lot of pain. Unfortunately, by the time they figure it out, it may be too late. \nRemember: The comments p",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Seesmic & BlackBerry",
  "date":"Tue Jun 28 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1309305600,
  "url":"/posts/2011/seesmic-blackberry/",
  "content":"Apparently Seesmic has announced that they're dropping support for BlackBerry users. You can read the announcement here: https://blog.seesmic.com/important-update-for-blackberry-users.html. Seesmic makes social media tools for mobile devices and, back when their solution was in beta, it was a highly anticipated product.\nI guess I'm not that surprised they're dropping support for BlackBerry, since BlackBerry and many other device manufacturers have made social media such an integral part of their on-device experience. RIM's support for Facebook, Twitter and so on – very much in your face on BlackBerry Device Software 6 would seem to make it hard for other developers to make compelling aps for the platform.\nIt's funny though, when you look at Seesmic's web site how very lame the BlackBerry version of their premier application looks against the others (although the iPhone version seems even lamer – that must be the wrong screen shot).\n\nWhat surprised me, and other people too (from reading reader comments on the Seesmic site), was this comment:\n“Effective June 30th, Seesmic will discontinue support for Blackberry in order to focus development efforts on our most popular mobile platforms: Android, iOS and Windows Phone 7.”\nToo bad they didn't know how to spell BlackBerry – they must not have been much of a partner to miss how RIM spell's the product's name.  Everyone gets iOS right, but doesn't even try to get BlackBerry right. Sigh!\nAnyways, back to my surprise. What surprised me was their comment that they're abandoning BlackBerry to focus on their most popular platforms which seem to include Windows Phone.  Windows Phone? More popular than BlackBerry?  Are they serious? I can see iPhone and Android, but Windows Phone? More popular than BlackBerry?  Ugh.\nI like Windows Phone. I've enjoyed using the Windows Phone devices and I'm even reading a book on Windows Phone development. But if Seesmic is seeing that Windows Phone is more popular than BlackBerry then the folks in Waterloo (RIM) really do have an issue.\nWhat's happening at RIM and the public outcry targeting the company saddens me.  I really, truly can't wait to see what they come up with as a strategy for getting out of this very visible slump they're in.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Concrete5",
  "date":"Mon Jun 27 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1309219200,
  "url":"/posts/2011/concrete5/",
  "content":"A while back I got really interested in content management systems (CMS). When I discovered Joomla!, I quickly created this site and hundreds of articles later it's still going strong. A few years ago, Wired Magazine (I think it was Wired) did an article about an open source CMS called Concrete5 (concrete5.org) and it looked…interesting. I installed a copy of it, but never really got the hang of it. I didn't have a site I wanted to build at the time, so I didn't really have a reason to use it and that probably affected my experience with the product. Ultimately though, I think I really didn't understand what it was. I was used to Joomla! and Drupal and expected Concrete5 to be like those other CMS's. It's not really, where normal CMS's are database &amp; template driven systems for displaying content, Concrete5 is more of a web site builder that uses a database in the back-end to store the content. It's for building sites with pages rather than creating articles, links and other things that are rendered by the CMS templates.\nI decided a few weeks ago to build the John Wargo Books site (https://johnwargobooks.com) and thought doing the site using Concrete5 would be fun. I quickly registered the domain, downloaded the files and got started. Knowing now that I was working with a site builder, it was really easy to populate the home page with the content I wanted (shown in Figure 1).\n\nOnce I had that done, all I had to do was add a navigational component (shown in orange on the right side of Figure 1) then create the additional 'pages' I needed for my site.\nThe cool thing about this tool is that your site building is all done in the browser. When you access the home page, you can easily login (the default Concrete5 template includes a login link in the footer, the template I'm using now does not) and directly manipulate the site using buttons that appear at the top of the page (as shown in Figure 2).\n\nTo edit a page, you navigate to the page then click the 'Edit page' button. To add a new page to the site, you simply click the 'Add Page' button and start typing your content. The system allows you to define a hierarchy for your pages then the navigational component automatically reflects your changes. There's plug-ins such as the 'Share' button and the site search shown in Figure 1. Behind the scenes there's a Dashboard view (shown in Figure 3) that allows you to configure the site as a whole.\n\nIn all, it's a pretty easy system to setup and use.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "My Books",
  "date":"Sun Jun 26 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1309132800,
  "url":"/posts/2011/my-books/",
  "content":"I'm getting ready to start writing my next (third) book. As I mentioned before, I've been having conversations with my publisher about what I'm going to do next and I think we've decided on the topic. I'm waiting on a contract from my publisher then I'll get started.\nIn the mean time, I decided to register a domain and open up a site where I can list information about my different books. Additionally, there's another John Wargo writing books so I have to have a way to distinguish my books from his. I brought the site up this weekend, it's called John Wargo Books and it can be found at johnwargobooks.com. Check it out when you get a chance and be sure to tell your friends!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Third Book",
  "date":"Tue Jun 21 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1308700800,
  "url":"/posts/2011/third-book/",
  "content":"I've been having discussions with my publisher about my next book. We talked a bit about doing an update to BlackBerry Development Fundamentals, but the market has really seemed to stall with regards to BlackBerry development books. Everyone's interests are now focused on iPhone and Android, but there's also a lot of great stuff being done in the cross platform development space.\nI got involved as a tech reviewer for the My Motorola Atrix book, and that was a lot of fun. I tried to get on the books for the BlackBerry Playbook and the BlackBerry Torch books in that series, but those titles were already taken.  I approached the publisher about doing a book on the new BlackBerry Bold, but it's mostly a consumer series of books and I'm not sure (and neither are they) how well the new Bold will fit in the consumer market.\nI believe my publisher and I have come to an agreement on my next book. All I need to do is write up a proposal and chapter outline and get it over to him for his review. I'm excited about the possibility and I'll let you know what it's going to be as soon as I start writing. stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Review of Advanced BlackBerry Development",
  "date":"Mon Jun 20 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1308614400,
  "url":"/posts/2011/review-of-advanced-blackberry-development/",
  "content":"Here's a review I wrote more than a year ago for Chris King's Advanced BlackBerry Development:\nJoining the flurry of BlackBerry books released within the last year is Advanced BlackBerry Development by Chris King (Apress ISBN: 978-1-4302-2656-7). Marketed as a sort of sequel to Anthony Rizk's Beginning BlackBerry Development, the book is supposed to kick it up a notch and dig into some of the more complicated things you can do with the BlackBerry Java platform. What you'll find though is that the book should actually be entitled “Mobile Java Development Including BlackBerry” – I'll try to explain below.\nOne of the things I've noticed lately as I read mobile development forums and the groups on LinkedIn is that when developers talk about mobile development, they usually generalize their comments and don't identify which area of development they're talking about: enterprise or consumer mobile application development. They both have very different needs, requirements and issues and effect how you look at a particular problem. Since I come from an enterprise development background, when I look at the title of this book, I expect to see advanced topics covered such as getting data from back-end data sources (especially connecting to XML-based and RESTful web services), dealing with encryption and security issues, plus managing the availability of different network connections. When looking at the topics covered in this book, it's clear that the author is looking at the topic from the consumer side of mobile development – he gives some cursory coverage to the BlackBerry development tools, connecting to files and networks then jumps into a consumer oriented media grabber application that pulls media files down from web sites. While the book does address more advanced enterprise-related topics such as integration with device-side applications and security, these types of topics take a back seat to topics such as playing and recording media files and sending or receiving text messages. There's nothing wrong with this approach, it just splits the potential audience for the book.\nIn digging through the chapters, the author does a really good job of digging deep into the major topic areas he's selected for the book. The book is broken up into three parts and each part covers a different area of BlackBerry Java development. Part 1 deals with what the author calls Advanced API's, part 2 deals with device integration and the last part deals with security and more developer oriented topics (as opposed to development-related topics).\nIn the advanced API's part of the book, the author describes in great detail how to capture media files (pictures and video), playback media files (audio and video playback), send and receive SMS, MMS and email messages plus use available encryption API's to encrypt data. For each of these topics, the author does a great job of explaining most available options and provides a wealth of source code that illustrates points made therein. What I found interesting though, was that as the author tackled a topic, in many cases he covered (in great detail) non-BlackBerry ways to address a problem before explaining the BlackBerry way of doing things. This is why I suggested the title change at the beginning of this review. What this book should cover is BlackBerry topics only – leave the other topics to any of the already existing JME books available to developers. The approach the author took here makes me feel that his target audience isn't BlackBerry developers, but JME developers who work with multiple platforms and are adding BlackBerry to their mix. Again, there's nothing wrong with this approach, it just isn't what I expected from an advanced BlackBerry book.\nEven the topic of cryptography is covered with a cross platform bias. Considering that the BlackBerry is the most secure mobile platform on the market, the author covers the open source Bouncy Castle cryptography API's before digging into the robust BlackBerry security API's and, recent purchase, the Certicom cryptography API's.\nIn the second part of the book, covering device integration, contains the most detailed description of how to integrate with the Personal Information Management (PIM) capabilities of the BlackBerry platform that I've ever come across. The material includes a detailed description of how it works plus a lot of source code to help you integrate the concepts into your applications. RIM provides some information on the topic in its API documentation, developer web site and sample applications, but this is complete coverage of the topic and very useful.\nThe next chapter digs into several aspects of the BlackBerry browser. It covers topics related to the different types of browsers and markup languages, then shows you how to launch the browser from your application and embed the browser in your own applications (none of which are really advanced topics). The chapter finally enters the advanced realm at the end with its cove",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Review of Beginning BlackBerry Development",
  "date":"Sun Jun 19 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1308528000,
  "url":"/posts/2011/review-of-beginning-blackberry-development/",
  "content":"Here's a review I wrote more than a year ago for Anthony Rizk's Beginning BlackBerry Development:\nConsidering how long the BlackBerry platform has been available in the market, it's amazing that there haven't been any books on BlackBerry development until very recently. There was Craig Johnston's Professional BlackBerry that was supposed to be a 'Programmer to Programmer™' book but ultimately had very little to do with BlackBerry development (except for some simple chapters on BlackBerry browser development and Push). Beginning in November, the first real BlackBerry development books were released (including mine) and the options a new BlackBerry developer had at his disposal increased dramatically.\nOne of the first books out of the gate was Beginning BlackBerry Development by Anthony Rizk (Apress ISBN: 978-1-4302-7225-0). The author was one of the founders of the long time BlackBerry ISV Alliance Partner Rove Mobile (formerly Idokorro) and recently started a software company called Zeebu Mobile which produces entertainment applications for children that run on BlackBerry smartphones. He's been developing BlackBerry applications since the very early days and clearly has the background needed to get you up and running quickly.\nThe first thing to know about this book is that it's not really about beginning BlackBerry development. It's actually about beginning BlackBerry Java development. If you're looking for a book to help you get started with all aspects of BlackBerry development, you're looking at the wrong book. This book is for Java developers getting into mobile development on the BlackBerry platform and for that audience the book performs well. I spoke with Anthony about the title before it was published and he indicated that the book was one of a series of Beginning X Development topics from Apress and he couldn't change the title to more accurately address it's audience.\nIt's not a long book; it weighs in at 238 pages and doesn't dig too deeply into highly technical topics. It starts with the basics then holds your hand through enhancing your application's user interface (UI) and adding common features needed by most BlackBerry Java applications (such as networking, location-based services and storing application data). The topics are covered in a clear and easy to understand manner and Anthony provided just the right topics for this entry level book.\nLet's dig into the content.\nThe book begins with the requisite introduction to the BlackBerry platform and the BlackBerry development tools. The overview is very high level, but if you're an experienced developer, it's probably all you need to get started. If you're an Enterprise developer and need to know more about what the BlackBerry Enterprise Server (BES) and BlackBerry Mobile Data System (MDS) do for you and your application, you won't find detailed information here. Since it's really a book for Java developers, and most likely targeted at developers of consumer applications, those details really aren't going to be missed.\nChapter 2 jumps into the standard Hello World application and uses the topic to help introduce you the ins and outs of the BlackBerry Java development environments (for those that don't know, the BlackBerry platform sports its own, free Java Development Environment [JDE] plus a more user friendly Eclipse plug-in). After you've built the application, your taken on a tour of the debugging capabilities of the platform's tools and educated on some topics that are often overlooked such as adding an icon to your application, setting the application's title, signing the application, testing on a device or a device simulator &amp; more.\nChapter 3 digs into the aspects of a BlackBerry Java application that makes it a BlackBerry application. It covers the BlackBerry event and thread models and how a developer needs to write her code to play nice on the device.  It includes coverage on how to update the UI from other threads and how to create libraries and use alternate entry points in your BlackBerry application to provide additional functionality for your users. The topics covered in this chapter are very important to the new BlackBerry Java developer and they're covered with just the right amount of depth to get you started recognizing that you'll use the BlackBerry API JavaDocs to dig into more of the details.\nThe next couple of chapters help you take a simple BlackBerry application and build a more compelling user interface for the application. The BlackBerry UI libraries, while very capable, just aren't generally used out of the box to create beautiful application interfaces. For someone like me, who's not a heavy duty Java developer, the topics covered in these chapters were just what I needed to understand how I can extend the base BlackBerry UI classes to create a pleasant look for any application. It shows you how to do some simple enhancements to enhance the look without doing any crazy, processor hogging and battery draining sp",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Developer Book Reviews",
  "date":"Thu Jun 16 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1308268800,
  "url":"/posts/2011/blackberry-developer-book-reviews/",
  "content":"Back in 2009, right after BlackBerry Development Fundamentals came out, I approached Dr. Dobb's Journal about writing some reviews of the other BlackBerry development books that were coming onto the market. The editor told me to go ahead, so I did the writing and submitted two reviews. Nothing happened; I'm not even sure the articles were ever read. So, what I'm going to do is publish them here next week.\nIt's two years later, my book has sold well but the BlackBerry development and mobile development worlds have changed a lot since then.  I was thinking of doing an update to my book, but I'm not sure that's going to happen. I'm not sure whether there's an update coming to Anthony Risk's Beginning BlackBerry Development. I see that Chris King has an update to his book, Advanced BlackBerry Development coming out soon, it's called Advanced BlackBerry 6 Development.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Review of Teamstudio Unplugged",
  "date":"Wed Jun 15 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1308182400,
  "url":"/posts/2011/review-of-teamstudio-unplugged/",
  "content":"The View just published my review of Teamstudio Unplugged, a mobile application platform for IBM Lotus Notes/Domino applications. The platform allows you to take an existing Notes application and mobilize it to the Unplugged client. Unplugged is essentially a mobile replication engine for Notes and BlackBerry (today, support for Android and iOS is coming soon).\nDevelopers use Xpages to craft pages that control how your Notes application data renders within the mobile application. The platform allows you to have more control over how things render on the mobile client, but requires more work to do it than Kryos AppXtender. It's really cool though how Teamstudio was able to implement this without requiring any additional software on top of a Domino server and out of the box Domino Designer.\nTeamstudio offers a free single user developer license for you to try out the platform. You can find additional information about the product at freeyourapps.com.\nThe article is called Mobilizing Domino Applications Using Teamstudio Unplugged, check it out if you're a subscriber.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "View Article Update",
  "date":"Tue Jun 07 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1307491200,
  "url":"/posts/2011/view-article-update/",
  "content":"I've got an article being published soon that digs into how to use Teamstudio Unplugged to mobilize Notes applications. I had a lot of fun working with their platform and found it to be a very interesting implementation. They created a synchronization engine and client-side development environment for mobile applications without requiring any plug-ins or additional development tools beyond two Notes databases and out of the box Domino Designer. Cool stuff.\nI've finished my work with PhoneGap. I took the BlackBerry Widget application I built to access my contact lookup web service and plunked it into PhoneGap and quickly built mobile applications for BlackBerry and iPhone. It was a very interesting project and I've written all about it in an article I've submitted to The View (eview.com). It was a lot of fun to work with the framework, but as with many open source projects, there's still a lot of work to be done to get everything working across all supported mobile platforms.\nI've started work on what the View calls a Thought Article - something I'm currently calling 'Preparing your Domino Developer Mind for Mobile' which tries to cover the process you go through as you prepare to mobilize a Notes application. I was going to work on finishing the article tonight, but I think I'll wrap it up tomorrow then give it a final read before passing it off to the View for publishing.It's basically a collection of my thoughts on many different aspects of Domino mobile development. Could be fun.\nNext up is an article about how to use Mobile Enterprise Application Platforms (MEAP) to mobilize Domino applications. In my job at AT&amp;T I work with most of the major MEAP vendors and this is really cool stuff. I've asked some colleagues to help me build mobile applications using each of the MEAPs so I can compare and contrast them in the article.I'm going to start writing that one next week.\nI'm also working with a colleague to write an article about how to build mobile applications for iPhone that talk to Notes databases. I tried to do this myself about 18 months ago and while I was able to get it 'working' I thought I'd engage a real iPhone developer to help me finish the article. Contrary to popular belief, iPhone development is much harder than development for any other mobile platform I've worked with, so it's been very hard for me to get this particular project done.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Moving Playbook Apps",
  "date":"Sun Jun 05 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1307318400,
  "url":"/posts/2011/moving-playbook-apps/",
  "content":"I received a BlackBerry PlayBook at the newly renamed BlackBerry World Conference in Orlando this year. It's an amazing device and except for a few little hardware and UI things (which I know will get fixed) I love it. I'm going to write a series of short articles on the PlayBook just to provide you with my feedback and to give you a general idea of what I think of the device.\nOne of the things I've been trying to do, and have not been able to figure out how to do, is to move PlayBook applications onto different tabs on the PlayBook home screen. I can't find any way to create my own folders nor have I been able to figure out how to move applications onto tabs. I'd like to setup a tab for my personal applications (vs. work apps) and move some apps there, but I cannot figure out how. I noticed something funny this afternoon which provided the subject for this post.\nTake a look at the attached photo - I can't move apps where I want them to be on the PlayBook, but someone at RIM has apparently decided that the BlackBerry World Conference Application is a game. Makes no sense to me.\n\nAnother question I have, and this applies to many smartphone platforms, why can't you have a longer application title and have it wrap on the screen? There's no reason why those application titles should be truncated when there's so much extra room available on the screen. Makes no sense to me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Going Cross Platform",
  "date":"Thu May 12 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1305244800,
  "url":"/posts/2011/going-cross-platform/",
  "content":"I came across an article in APC Magazine this week that discusses problems developers have with cross platform mobile development. The article is called Smartphone Devlopment: Going Cross Platform and what interested me was what was being said about iPhone development.\nThere's this perception in the market that since the iPhone platform is so cool and the apps are so beautiful, that it must be easy to develop for the platform. There's so much bias out there in favor of the iPhone that it is hard to get an honest assessment without appearing bigoted against iPhone.  I did some iPhone development in preparation for a conference presentation last year and even though I had more than 20 years of experience as a professional software developer, the development approach to iPhone development and the archaic Objective-C were so hard to work with that I wasn't able to finish the application in time for the conference session. I worked on it for weeks and weeks and had to give up because it was just incomprehensible to me.\nApple Macintosh and iPhone development is done using technologies Apple obtained when it purchased NextStep back in the 80's. Objects such as strings start with NS, NextStep, so instead of working with Strings, you have to work with NSStrings. Why they can't be just strings makes no sense to me, but that's the way it is. The iPhone platform has no garbage collection capabilities – developers have to track everything and make sure memory is freed up when an object is no longer used. Everything is a pointer; there's no direct access to variables, it's all pointers to variables. It's very 1980's.\nI laugh when I hear people complain that the BlackBerry development stuff is 'old' – I'm old enough to know that the iPhone stuff is even older. Most modern languages have some sort of garbage collection mechanism. BlackBerry and Android have it because of their use of Java. Not true in iPhone development – you have to do the work yourself.  Ugh!\nLet's take a look at some important tidbits from the article:\n\n“Going to iPhone development feels like a backwards step from programming in managed environments like Java and .NET, where memory management, exception handling and the like are automatic,” \n\n\n“The iPhone stuff is still in the dark ages in terms of programming environments: you've got to keep track of everything,” he continues. “Objective C tries to make sure everybody understands who's responsible for freeing up what, but it feels like going backwards; being able to have Java-like memory management makes a big difference for developers.”\n\nIn a rapidly-growing market where iPhone support is the de rigeur standard for developers and a necessary step to access the world's largest and most successful App Store, Powell's comments may sound like heresy. But with Android having rapidly emerged as a viable alternative over the past year, it reflects the growing realization among many developers that iOS is no longer the be-all and end-all of mobile operating systems.\nNeeding to build and maintain two or more versions of a smartphone app raises the difficulty level of many development projects significantly, particularly for small developers. “iOS and Android are very different platforms,&quot; says Bradby. &quot;Someone who's skilled in Java say, doing Android, is not necessarily and unlikely to understand the Objective C and XCode development environment for iOS. Having a team of developers that can maintain both of those code bases is difficult; there's no way we can do native development on more than two platforms.”\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "PhoneGap",
  "date":"Tue May 10 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1305072000,
  "url":"/posts/2011/phonegap/",
  "content":"I started working with PhoneGap today. I've been poking around the framework for a while now and I finally got around to actually working with it. As with most Open Source projects, I find that the documentation is sorely lacking.\nI'm building a PhoneGap application that uses the Domino RESTful web service I documented in a previous article on this site (Mobilizing Domino Data Using REST: Part 1). I'll be using what I'm learning now in one of my sessions at the View Domino Developer Conference. Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Gartner, MEAP and RIM",
  "date":"Tue May 10 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1305072000,
  "url":"/posts/2011/gartner-meap-and-rim/",
  "content":"In my role at AT&amp;T I work with customers looking to mobilize Business to Consumer (B2C) and Business to Business (B2B) applications using Mobile Enterprise Application Platforms (MEAP). MEAP is a term I believe was coined by Gartner a few years back and since it's their term, their publications on MEAP are the industry's reference on the topic.\nIn December, 2009 Gartner published a MEAP Magic Quadrant document that talked about the different MEAP vendors, their capabilities and how they were faring in the market. It wasn't until April, 2011 that the next edition of that publication was published and it contained some interesting information.\nFirst of all, for those of you who understand Garter's Magic Quadrants, any vendor wants to be in the upper right corner of the quadrant. That's the place for the movers and shakers, the innovators and the ones to watch. For this year's MEAP Magic Quadrant, the upper right corner is empty.  Yep, empty. None of the MEAP vendors are perceived by Gartner to be leaders in the space. I thought that was weird. How can you have 10 or so vendors and none of them being leaders?\nAnyway, the thing that caught my attention was how out of touch Gartner is about what RIM is doing in the market. In the 2011 MEAP Magic Quadrant document (Magic Quadrant for Mobile Enterprise Application Platforms) and another document I just read this morning called Critical Capabilities for Mobile Enterprise Application Platforms (ID #G00212257) Gartner refers to the RIM MDS Runtime client and development tools. The interesting thing about that is that RIM discontinued the MDS Runtime development tools and runtime client in December 2009. So in this case, Gartner is making statements and assessing RIM's capabilities using products that RIM discontinued about 18 months ago.\nHow can Gartner be effective and accurate if they base their analysis on products that are no longer even produced or supported by the vendors? That makes no sense to me. The MDS Runtime tools were great and I am disappointed that they're no longer available, but they're gone now – never to return. Gartner needs to pay attention.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "What Were they Thinking 8 (part 2)",
  "date":"Thu May 05 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1304640000,
  "url":"/posts/2011/what-were-they-thinking-8-part-2/",
  "content":"A few hours after posting my article about the BlackBerry World conference application, RIM released an update to the program. I can't imagine what change would be so important to release an update to the application in the middle of a four day conference, but they did. Must have been a bug.\nWhen I opened the application the first couple of times after installing the update, instead of the default 'please wait 2-3 minutes while the application loads' that I complained so much about, the application showed a blank screen (with a web browser cursor for some bizarre reason) for a really long time before opening. I imagine that it was somehow updating the existing data in the application or upgrading a local database, but it took a really long time without any indication on the screen what was happening. I even pulled the battery and tried again to see if I was having a problem with my device.\nThat's not good programming.\nOne of the things I noticed as I worked with the application was that the developer didn't make any accommodation for changing the orientation of the device. I use a BlackBerry Torch 9800, from AT&amp;T of course, and it has a touch screen and slide out keyboard. I can change the orientation of the device and get better screen real estate for the browser and some applications.  When you look at the application in portrait mode, you'll see something similar to what's shown in Figure 1.\n\nFigure 1\nWhen you switch the device to landscape orientation, you'll see a screen similar to the one shown in Figure 2.\n\nFigure 2\nNotice that the screen doesn't orient itself to make full use of the screen real estate available when the device is in landscape orientation. This makes no sense to me. BlackBerry Device Software has API's that allow the developer to react to orientation changes since BlackBerry Device Software 4.7. These API's allow a developer to adjust the layout of their application's screens when the user rotates the device. The application clearly adjusts the header so it looks correct in this orientation, but why didn't they make it so the home screen options adjust their layout as well?  What's the sense in making me scroll down to access the third row of icons when I have the room to fit at least two of them in that blank space to the right.\nIt's just sloppy programming – how could this have been missed? Did they expect that the user would never turn their BlackBerry touch-screen devices on their side?\nNotice too that in Figure 2 you can see the pointer (the arrow cursor) on the screen. It's a touch screen device, why show non-touch screen controls when running on a touch screen device? Another example of sloppy programming. When touch is not available, that's a useful navigational element. On touch screens, in this case I've touched between icons to bring up the cursor, it's not needed. There's no need to show the cursor when I've touched the screen, I can't use my finger to move the cursor (not that I'd want to), so it should be turned off when running on this device. \nIt's RIM's app, they released it in support of their premier customer conference. They're spending a lot of time and money promoting their concept of Super Apps https://us.blackberry.com/developers/started/super_apps.jsp but when they release an app for their conference, the hire a developer that can't make accommodation for orientation changes or integration with the device calendar?  That's sloppy, very sloppy.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "Multiple-login Smartphones",
  "date":"Wed May 04 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1304553600,
  "url":"/posts/2011/multiple-login-smartphones/",
  "content":"Why can't you login to your smartphone? You can password protect them (either set by the user or required by an enterprise administrator), but why can't you log into them?\nI got started in the mobile apps world many years ago. RIM hired me to be a mobile apps evangelist for AT&amp;T's customers. I worked with mobile apps at BoxTone and in my current role at AT&amp;T I work with mobile application platforms that allow organizations to build one application that runs natively on multiple mobile device platforms. Over the years, the whole mobile apps story got easier and easier – organizations were getting over their concerns about mobile apps and actually starting to do something interesting with them.\nUnfortunately now that Enterprises have to deal with the iPhone and Android platforms, many organizations have essentially put the kibosh on applications initiatives while they figure out the whole mobile device management (MDM) thing.\nI've been in meetings and conference sessions lately that deal with device management and it's clearly something that organizations are struggling with. BlackBerry shops have it easy since the BlackBerry Enterprise Server (BES) takes care of so many of the things IT and Security departments require, but with today's proliferation of device types, the BES isn't enough. With this week's announcement of RIM's acquisition of Ubitexx, it's possible that RIM can solve this problem – who knows.\nWhat's interesting though is how the ultimate solution to most organization's mobile device management problems is clearly known, but it's impossible for third party software developers (such as the market's MDM providers) to implement. The ultimate solution has to be a core part of the device operating system, not an add-on that has to work around existing API's and device limitations. What smartphone manufacturers have to do is provide the means for the smartphone users to have the ability to define distinct logins for multiple users on the device.\nFor the enterprise, an enterprise aware smartphone would have the means to allow the user to have a personal login (with access to all of your personal data and accounts) and another separate corporate login with access to work-specific information (data, applications and accounts).  As the user logs into either account, he or she is exposed to only the data that's associated with the account. This makes perfect sense – give me complete separation between my work and personal activities and most of the enterprise's concerns go away.\nThe phone would have to support managing multiple phone numbers, but that technology exists already today. The user would have their personal phone number associated with one account and a work mobile number or a work mobile and office numbers associated with the enterprise login. When the phone rings, the device would have to be able to switch on the fly to the personality associated with the phone number that's ringing or at least be able to access the caller ID information (from the address book) stored  with the account associated with the phone number so it can be displayed to the user.\nCommon applications (such as email, calendar, contacts and more) can be shared across multiple logins, but individual custom apps could be installed in a private memory area. There would be no common data shared between logins though except perhaps log files.\nThe same feature can be used to make tablets more useful as well. It makes no sense for consumers why tablet manufacturers don't allow devices to have multiple accounts. Any family with an Android tablet should be able to define multiple accounts and easily switch between them. That way, I can setup my preferences and account information (mail, facebook, linkedin and more) and when my wife or one of my children logs into the device they see their individual settings instead of mine. Why isn't that possible?\nClearly it's a direct decision made by device manufacturers – these tablets are so popular and sexy, but limiting this capability forces people to buy more tablets. I have one, my wife would have one and each child would need one too. Implementing multiple logins, while completely possible, would result in reduced sales for the device manufacturers. That's ultimately what's keeping manufacturers from implementing this in my opinion.\nWhat would have to change in order to support this feature I'm describing? Well, devices would need more memory; I'm guessing twice as much. There wouldn't need to be changes in the processing power and battery for the device, it's still doing the same amount of work. I imagine when you login to a second account, the applications being executed under the first login would need to be suspended or terminated. Everything else stays the same, right?\nCarriers benefit since the device will be provisioned with multiple mobile numbers, so there's increased revenue for the carriers.\nLet's start lobbying the device manufacturers for this capability. It makes",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "What Were they Thinking 8",
  "date":"Tue May 03 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1304467200,
  "url":"/posts/2011/what-were-they-thinking-8/",
  "content":"I'm at the BlackBerry World conference this week and I thought it was a good time to add an article to the What Were They Thinking series. The example for this article is the conference application for the BlackBerry World conference in Orlando. RIM has hired different developer organizations to create the different applications, there was the Sweet Ceasar applications commissioned for the BlackBerry Developer conference which used so many fancy screen effects that the application was unusable. What happens is RIM is trying to demonstrate how cool applications can be on the BlackBerry platform and encourage these developers to do all sorts of fancy things to highlight that. Unfortunately what you end up getting is something unusable and this year's BlackBerry World Conference application is no exception. When you focus on flash rather than functionality, the end user suffers.\nTake a look at the following screen shot; you'll see the warning that it will take from 2 to 3 minutes to load the data for the application. Unfortunately, this delay (and the corresponding warning) happens every single time you load the application (yep, every single time). I don't know about you, but no mobile application should take 2 to 3 minutes to start up; that's completely unacceptable.\n\nFigure 1\nWhy do that? Why not cache some or all of the data? This approach essentially makes this application unusable. I expect that there's an expectation that you'll leave the application running during the day, but I don't use mobile applications that way. I use the application then escape out so I can recover some memory and not have a bunch of applications running in the background all the time. Steve Job's approach is to deny you an Escape button, so every application suspends when backgrounded, but it's much better (for me anyway) to just let me decide what happens. \nWhat a developer should have done is preload the application with a default set of options then display an application's main screen and load additional data in the background.  Let me at least work with some non-dynamic data or the data from a previous load instead of making me wait for a data load every single time the application launches.\nSomebody wasn't thinking.\nAnother thing I noticed was that there is no provision for me (or at least I can't seem to find it) to be able to add items from my schedule to my calendar. Previous year's application allowed that, but this year's doesn't. That doesn't make sense to me since RIM has made such a big push for Super Apps. Super Apps are supposed to be all about integration with other applications and activities on the device, what I can't understand then is why I can't register for a session at the conference and immediately add it to my BlackBerry calendar.\nWhat I have to do instead is open the conference app every time I want to see what my event schedule is. Since that takes 2 to 3 minutes, that makes it a tough thing to do when trying to rush from session to session. \nSomebody wasn't thinking.\nOne good thing I saw was that the developer coded the application so the 'my schedule' portion of the app doesn't show days where you don't have sessions scheduled. If you take a look at Figure 2, you'll see that it's not showing events for Thursday because I don't have anything scheduled for that day. That's good attention to detail.\n\nFigure 2\nUnfortunately, what they did with this option is the same thing that other vendors have done with other conference apps. When I open the application on Tuesday for example, it should automatically highlight the current day in the schedule. Instead, I have to click on a day or scroll down to a day and press return. If they'd thought about the use cases, they would have realized that if I'm looking at the schedule, there's a high likelihood that I care most about the current day's schedule before any other option.  Don't force me to pick the day every single time I look at the schedule when you know that today's what I'm most likely to need.\nWhat I would have done is opened the current day's schedule automatically (why make me click?), then give users the ability to easily pick another day of the conference. It's only a three (or four day depending on how you look at it), how hard would it be to implement a more efficient way to look at my schedule?\nCompanies need to focus on usability before anything else.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "Using the Motorola Atrix",
  "date":"Tue Apr 12 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1302652800,
  "url":"/posts/2011/using-the-motorola-atrix/",
  "content":"As I've written about here, I've been trying out all sorts of new mobile devices. Working for a carrier certainly has its benefits and getting one of every new smartphone is one of them. I have been very interested in seeing if I could carry an Android device full time and the Motorola Atrix seems like it could be the device for me.\nI'm not abandoning the BlackBerry platform, but Android is…cooler and I don't have someone like Steve Jobs deciding what I can and cannot do on my mobile phone.\nAnyway, some initial observations about the Atrix:\nFirst of all, it's FAST. One of the problems I had with the Samsung Captivate and other Android devices was that they're often unresponsive. When I would turn on a device and try to type in my password to unlock the device, it would often not be able to keep up with my key presses. Ugh.\nI really miss the BlackBerry platform's ability to set a system wide font. As I get older, I am having a harder and harder time reading smartphone screens without my glasses on. On the BlackBerry, I can define system wide font settings and make the screen more readable for me in many applications, but Android doesn't have anything like that. I'm pretty sure I won't be able to use this device everywhere simply for the reason that I won't be able to read it without my glasses and I don't bring them with me everywhere.\nI'm not a fan of Moto Blur (or anything like that added by device manufacturers). Why can't I just have Android as Android? Why do I need the extra UI and applications layers that Blur and the other systems add? Makes no sense to me – get out of my way.\nThe Atrix has three email clients and they each work differently. Ugh! Why does there need to be three of them? The BlackBerry has one, so I can do the same things in different email accounts. The Gmail messaging client allows you to control what happens when you delete an email – you can go back to the message list or an older or newer message in the message list. I like that feature. The corporate and personal email clients? No such thing. For some ridiculous reason when you open a message then delete it, you're taken back to the message list and have no configuration options that can change that behavior. Ugh! When I open a message and delete it, I want the messaging application to open the next message in the message list. Making me go back to the message list and select another message to open adds clicks to my experience and makes it take longer to get through my inbox.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Kryos AppXtender Shipped",
  "date":"Sun Apr 03 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1301875200,
  "url":"/posts/2011/kryos-appxtender-shipped/",
  "content":"I've been so busy since Lotusphere (ya, I know - that was months ago) that I never got around to letting all of you know that Kryos AppXtender shipped in February. If you haven't heard about AppXtender, it's pretty cool - it's a tool you can use to mobilize your existing Domino databases. The folks at Kryos asked me to be a bete tester for the platform and I really enjoyed working with it. I demonstrated the platform in my session at Lotusphere 2011 and published an article in the View that showed how it works - View subscribers can read the article online.\nWhen you get a chance, take a look at the announcement.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "BlackBerry Widgets & Domino",
  "date":"Fri Apr 01 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1301702400,
  "url":"/posts/2011/blackberry-widgets-domino/",
  "content":"For those of you who are interested in BlackBerry Widgets (BlackBerry WebWorks) and how you can use them to talk to IBM Lotus Domino applications, The View just published an article I wrote called BlackBerry Widgets — A Fast, Easy Way to Mobilize Your Domino Applications. In the article, I use the RESTful agent I illustrated on this site to build a BlackBerry Widget that talks to the Domino service. It was a fun app to write and I'm very proud of the article.\nI wish I could share the information from the article here, but it belongs to the View. Check out the article if you're a subscriber. I'll be demonstrating the application (and how I built it) at the View Domino Developer Conference in Las Vegas in June.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Book Shopping",
  "date":"Tue Mar 22 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1300838400,
  "url":"/posts/2011/book-shopping/",
  "content":"I was poking around in a mall in Plano Texas today and stopped by a Barnes &amp; Noble just to see what's new, but of course to see if my BlackBerry book was on the shelves.\nAs I looked through the computer books I noticed something that's really indicative of the smartphone market. There were a TON of iPhone and Android development books (I didn't count, but I imagine there were around 30 or more overall) and even quite a few Windows Phone development books. As I searched and searched throughout the whole computer book section I only found one BlackBerry book.\nNow, the good news is that the only BlackBerry book on the shelf was my book (BlackBerry Development Fundamentals), but how sad that with the 15 or so BlackBerry books on the market, there was only one on the shelf. As much as RIM's still selling a bunch of devices, it's clear they're losing mindshare.\nIt's cool to see my book on shelves, and I usually mention to the sales clerk at checkout that I am excited to see my book on the shelf. When I do this, sometimes the clerk acts excited for me (which happened today) but sometimes the clerk acts like it's no big deal. I'm not famous or anything, but they can't have that many authors come in off the street, can they? I secretly hope they'll ask me to sign the book, but that never happens. Why is that?\nWouldn't you be more interested in a book signed by the author? Why not have a pack of post-it notes that says something like 'Signed by the Author' with a place to sign - they could then post it inside the cover and someone who wanted it could keep it and someone who didn't could pull it out and throw it away. That wouldn't be that bad, would it?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Google Analytics & Domino",
  "date":"Sun Mar 13 2011 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1300060800,
  "url":"/posts/2011/google-analytics-domino/",
  "content":"If you have a public-facing web site that you maintain, you're probably aware of the capabilities provided by the free Google Analytics  (GA) service. Essentially it's a web-based web metrics application that you can use to understand a whole bunch of stuff about your site's visitors.\nI use the service to track visitors to this site and several other sites I maintain, it provides you with a lot of very useful information. I can tell how steady my site's traffic is, where people are visiting from as well as what type of hardware and software visitors are using to access my site. Another interesting feature is traffic sources, I can tell how people are finding my site - which would be very useful information if I were advertising and trying to understand where I should be spending my advertising money.\nGA tells me which articles are the most popular, allowing me to see trends in readership interest. Of course, if I cared about my readers (and I truly do), I could use information about which articles are being read to help guide me on what to write about next. The big question for Domino developers though is how do I effectively use GA to help me track readership in my Domino-based public web site?\nLotus Domino web application URL's are...ugly. Lotus has built a great system for managing content on the web, but the behind the scenes URL Domino uses to represent a document in a database doesn't translate very well in GA. You can add analytics to a domino application, but when you look in GA to see which articles are being read, what you'll see is those funky Domino URL's; you won't really be able to tell which documents or views are being opened unless you can translate Domino's internal URL into something more useful.\nYou can easily build your Domino application so all links are more human readable, but when you open a document from a view in a Domino database, the URL reported to GA is the internal one maintained by Domino rather than something human readable. To help Domino developers get around this, I recently published an article in The View called Creating Domino-Friendly Entries in Google Analytics that describes in detail how to use special features of GA to allow a developer to control what URL information is delivered to GA. The article contains a sample Domino application that illustrates the implementation. Check it out when you get a chance.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Domino & Dashcode",
  "date":"Wed Mar 09 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1299715200,
  "url":"/posts/2011/domino-dashcode/",
  "content":"As you know (or may not know) I've been working on a series of articles for The View on mobile development for IBM Lotus Domino. I've tried to identify each of the ways you can mobilize Domino and Notes applications then write an article about it. I proposed a series of about 15 articles and the most recent article (#5 in the series) was just published today. It's called Mobilize Notes Applications to iPhone and iPad Using Apple Dashcode and it was a lot of fun to write. The article essentially shows you how to connect a web application created using Apple's Dashcode web development environment to a Domino database. The article shows you step by step how to build the application and test it on the iPhone simulator.\nFor many applications, building native mobile applications to talk to Domino can be a bit daunting (understatement), but using the code generating capabilities of Dashcode made it really easy. Check out the article when you get a chance.\nThe next article in the queue for the View is an article on how to modify your Domino applications to get more useful statistics out of Google Analytics. I'm hoping that one will be published soon as well.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Mobile Device Heaven",
  "date":"Wed Feb 23 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1298505600,
  "url":"/posts/2011/mobile-device-heaven/",
  "content":"I've been in device heaven the last couple of weeks. With all of the new devices AT&amp;T has released and finally having some time to play around with them, I've been having a blast.I've got 7 devices here on my desk and I'm playing with all of them.\nWindows Phone 7\nI got a couple of Windows Phone 7 devices before Christmas and I've been using them the last week or two (I've even taken one of them as my primary device for the week). As I said in my post yesterday, I've found that Windows Phone 7 is a much better operating system than I expected. It's clean, crisp and responsive – I actually like it. Not more than my BlackBerry, but I do like it. It would be very interesting to see what this looked like on a tablet.\nGalaxy Tablet\nI got a Samsung Galaxy Tablet and I have to say that I truly love it. I know Steve Jobs is poopooing the smaller format, but it's really, really compelling. The fact that Android is open and I can do essentially anything I want with it (as opposed to what Apple 'allows') makes it awesome. The form factor is great – it's big enough to be really useful, but small enough to be very comfortable in your hand (as opposed to hands). As my wife said this morning “that's something I could fit in my purse” and that particular though is really more compelling than you'd expect.\nMotorola Android Devices\nI'm excited about using the Motorola Android 2.1 Bravo and Flipside devices. I really expected the Captivate to be the device I could carry full time, but it was so unresponsive most of the time that I just couldn't use it. We'll see what the Moto devices feel like.\nBlackBerry Playbook\nI'm not getting the feeling that the BlackBerry Playbook is going to be a better experience than the Galaxy Tablet. The only thing it has going for it is the tight integration with the BlackBerry device. Since Research in Motion is supposedly planning on a Cellular version of the device (to be released later), I don't see that feature remaining that compelling. Research in Motion supposedly sees people who don't currently own a BlackBerry device being interested in the Playbook, but I don't see it. I can't imagine someone buying a playbook over the iPad or the Galaxy Tablet unless they are currently a BlackBerry user and want to stay that way. Any other reasons don't make sense to me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Managing Email Folders & the Grand Mobile Experiment",
  "date":"Tue Feb 22 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1298419200,
  "url":"/posts/2011/managing-email-folders/",
  "content":"When I first joined AT&amp;T, my boss challenged me to see how long it would take before I switched full time to the Apple iPhone. Once I got settled, I put aside my BlackBerry device and tried to make the switch. My plan was to see if I could use it for two weeks solid; I made it 10 days before I had to switch back to my BlackBerry.\nIt's not that I'm a BlackBerry bigot, I love technology and playing with different devices. I promise you that if I could find devices that worked the way I needed to work, I'd be happy to switch around between different ones. The problem is that BlackBerry has been optimized for the things I do the most, regular everyday email. Every other platform I've used tries, but comes up short in so many ways.\nHaving worked for Research in Motion, I'm a heavy email guy. Because of the instantaneous nature of BlackBerry email, everyone at Research in Motion uses email heavily, even to the point where email was an easier way to reach a colleague than making a phone call. You knew that no matter what the person was doing, especially being on the phone, that they'd be checking their email regularly. Interestingly as these other device platforms (iPhone, Android, Palm and others) try to tackle the enterprise, it's just not possible for them to accommodate the business email user.\nWhat I've noticed with these different platforms is that they're not designed to deal with a user who has a large inbox. On the BlackBerry for example, I can highlight a date, click the menu button and very quickly remove any messages from the device older than the selected date. It doesn't remove them from your mailbox, just removes them from the device. On the iPhone and Android devices, when you want to clean up your inbox, you have to click each email individually to delete them – that's ridiculous.\nIf you're a heavy email user like I am, you probably have hundreds if not thousands of folders in your inbox.  When I get an email, I deal with it, delete it if I think I won't need it anymore and file it if I think I will need it again. On the BlackBerry, I merely press the 'I' key on the keyboard and the list of folders appears. If I'd filed a previous message on the same thread, the BlackBerry will automatically highlight the last folder used for messages on that thread. When I select a folder and press the Enter key it's filed. The whole process takes very little time. Pretty cool.\nWith other device platforms, you have the ability to file messages, but when you activate that function, the complete list of folders displays. There's no keyboard entry, you have to swipe through every single page of your folder list to get to the one you want. It's ridiculous. I have hundreds of folders in my inbox, why make me swipe through page after page of folder names to get to the one I want to file my message in? It makes absolutely no sense to me. This is what I mean when I say that most platforms aren't setup for enterprise email users.\nNow, you might be saying to yourself “Well, the BlackBerry works that way because it has a keyboard – that's an easier thing to do with a keyboard.” Unfortunately that's not the case. Even on a touch screen device, Research in Motion provides you with the means to bring up a keyboard and start typing the name of the folder you want to file your message in. It's an extra click, but it still allows me to file the message pretty quickly.  On iOS and Android, the user is not provided with any means to use the keyboard for folder selection. Apple and Google have decided for you that you're not allowed to use the on-screen keyboard when filing messages. Makes no sense to me.\nWhy not provide the option to use the keyboard? Default to using your finger to swipe through the folder list, but for people like me who have hundreds of folders, let me select the folder I want to use via the keyboard.  These devices are supposed to be so cool and so hot, but something as simple as filing email messages is broken. Like I said at the beginning of this article, these mobile platforms are not designed for the enterprise mail user.\nAnyway, on to the Big Mobile Experiment… Today I moved my SIM from my BlackBerry Torch 9800 into a Windows Phone 7 device.\nI was playing last week with the HTC Surround and this week I'm poking around in the LG Quantum. The Surround was pretty cool – I didn't need the extra weight and thickness provided by the surround speakers, but it was a functional device. I thought I'd like the Quantum because it had a keyboard, but I found that on Windows Phone devices a keyboard is actually a detriment to the end user.  I've found repeatedly that the UI for many aspects of the phone doesn't rotate to the keyboard orientation when you slide out the keyboard. If the UI doesn't switch for keyboard input when you expose the keyboard, what's the point of having the keyboard?\nAnyway, I'm going to use the Quantum as my primary device this week and see how I like it. So far, Windows Phone 7 is better th",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "BP209 Lotusphere 2011",
  "date":"Sun Feb 06 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1297036800,
  "url":"/posts/2011/bp209-lotusphere-2011/",
  "content":"Note: removed obsolete attachments November 11, 2022\nAttached is the presentation that Rob Wunderlich and I presented at Lotusphere 2011. The session was entitled BP209 Delivering IBM Lotus Domino Data to Mobile Devices: More Stupid Tricks and in it, Rob and I revisited our Ten Tricks for Mobilizing Domino from Lotusphere 2010. For this year's session, we took a look at last year's tricks and identified which ones didn't matter so much anymore (since the market changed the way it looked at the requirements) and tried to come up with some new ones.\nThe attachment is below, the following image is just a screen shot of the first page of our presentation.\n\nOne of the things I did in the session was demonstrate some applications. I showed how to use Apple's Dashcode development environment (Dashcode is a code generator for Safari web applications) to build an application that talked to a Domino data source. I tried to build the application in less than a minute but was only able to do it in a minute and two seconds. Drat. It was still fun to do - I quickly built the app then went back and showed what I did. The complete walkthrough has been submitted as an article to the View and should be published in the next couple of months.\nI also demonstrated how to build a BlackBerry WebWorks (Widget) application that connected to the same Domino data source I've used on this site for many examples.The complete walkthrough of this application has been submitted as an article for the View and should also be published in the next couple of months.\nHaving participated in the beta of the Kryos Velocity Designer for Lotus Domino (now renamed Velocity AppXcellerator for Lotus Domino) I was able to show how to use the Kryos platform to mobilize a Domino database.\nIn all it was a lot of fun and I hope I can do it again next year.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "First Impressions of Titanium",
  "date":"Wed Jan 26 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1296086400,
  "url":"/posts/2011/first-impressions-of-titanium/",
  "content":"I've been poking around at Appcelerator Titanium for the last week or so and I have to admit that I'm really not impressed. It looked like a really interesting solution, but:\n\nThere's absolutely no documentation - what 'documentation' they do have is nothing more than a sample application called Kitchen Sink that has examples of everything Titanium can do inside of it.\nIt took me hours (and I do mean hours) to get the kitchen sink demo to run in the Android simulator. I followed Einstein's definition of Crazy (doing the same steps over and over again expecting different results) before it finally just worked. There's no docs on how to run it, no instructions, nothing. You can find all sorts of posts on their help area from people who had the same experience I had. I finally found something that explained why it wasn't running. I implemented the fix and still couldn't get it to work. I created several new VM's with clean configs and finally on about the 6th try it finally worked.\nScreen transitions are slow, applications seem hesitant when running.\nThere's absolutely no layout manager that I can find. When you add objects (such as buttons, fields and so on) to a screen, you have to provide absolute positions for every single element. You can't plunk a label down then add a edit field below it, you have to add both manually, specifying two coordinates (top, left, right, bottom) for each. It absolutely makes no sense that in 2011, with all of these cool smartphones around that you'd have to take that approach to writing applications.\n\nGranted I'm using the free version, but you'd think there's be something better than this.\nI LIKE the idea that mobile development in Titanium is all about code - you hand craft code for everything, I truly like that. But to force me to determine EXACTLY where to put things is ridiculous. How do I know where my label is going to end (with word wrap, font size and so on)? Why do I have to manually, physically put every element in its place?\nIt just over complicates applications when you have to code at that level. It's easy for iPhone devices since you only have two real screen resolutions to work with (three if you count the iPad - which you should). But with all the different Android and BlackBerry devices out there, writing specific code for each screen resolution so that screen elements show up where they're supposed to makes no sense.\nWhat's surprising as well is how long it's taken them to come out with BlackBerry support. It's been in beta for a very long time - I am curious what's going on with that.\nI've got to be missing something here. Stay tuned, I'm going to try to build a Titanium version of my contact lookup app and see what I can come up with. I bet I won't be able to do what I want within Titanium.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Kryos AppXtender and More",
  "date":"Wed Jan 19 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1295481600,
  "url":"/posts/2011/kryos-appxtender-and-more/",
  "content":"A while back I started a series of articles in the View about mobile development for Domino. The first article was called Mobile Application Development Trends — What Today's Developer Needs to Know Now which was an overview of what I saw as trends in the mobile development space. It really had nothing to do with Domino development, it was just an analysis of the market. I followed up with two articles about developer's options for mobilizing Domino databases. The first article was called Taking It With You, Part 1: Know Your Options for Mobilizing Domino Databases via the Web and the second was called Taking it With You, Part 2: Mobilizing Domino Databases Using Native Clients, Hybrid Applications, and MEAPs. About that time I realized I had a series on my hands and I flushed out all of the articles I wanted to write about mobilizing Domino. Essentially what I did was identify all of the possible options I could think of and planned to write an article about each one of them.\nThe View published the fourth article in the series yesterday, it's called Mobilizing Domino Data Using Kryos Velocity AppXtender. Kryos is about to release (if they haven't already) a pretty cool platform for mobilizing Domino applications called Velocity AppXtender; I was invited to participate in the beta program and found the platform to be pretty interesting, complete and well thought out. They'll be making a big splash at Lotusphere 2011 I'm sure, so check them out when you get a chance.\nIn preparation for my session at Lotusphere this year I got to spend some time with Dashcode and the BlackBerry WebWorks tools. Subsequently I wrote articles about each of those tools for the View. They're both written and they're being processed by the very capable editing staff at the View. Next up on my agenda are articles about TeamStudio Unplugged and Wallace Wireless' WIC DB. I have the TeamStudio software, I just need to find some time to dig into it. Unfortunately I'm having difficulty getting my hands on the WIC DB product. I spoke with the President of Wallace about a month ago and let him know about the article series. He promised to hook me up with the code, but I've heard nothing from them since then. I followed up via email and received no response. I went to their site today and noticed that they were acquired by Vocera, so perhaps that's why they have become unresponsive. We'll see what happens, I'll try them again soon.\nI've also been poking around at Appcelerator's Titanium product. It looks very interesting and, with their acquisition of Aptana this week, makes them a pretty interesting option for mobile development. Unfortunately being a typical open source project (with a paid subscription option) their documentation is non existent. I've been looking at everything I can find on their site and there's nothing there that can help me get started. They have this kitchen sink application that you are supposed to look at to see how to do everything in their platform, but I just can't get the thing to load in the simulator. No useful error messages or anything, it just won't install in the simulator and I can't figure out why. It's really disappointing me since I really wanted to show my BlackBerry Widget application in Titanium. Hopefully I'll be able to make something happen soon with that.\nStay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Mobilizing Domino Data Using REST Part 1",
  "date":"Tue Jan 18 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1295395200,
  "url":"/posts/2011/mobilizing-domino-data-using-rest-part-1/",
  "content":"The first part of a series on mobilizing IBM Lotus Domino data for mobile platforms that don't directly support XML-based Web Services (like Android and the iPhone).\nIntroduction\nNote: removed obsolete attachments November 11, 2022\nBack when I worked for Research in Motion, I presented topics at Lotusphere and the View Developer Conference on how to connect to Domino databases from rich client applications on BlackBerry. Research in Motion had some pretty cool tools at the time (MDS Studio) that made it painfully easy – I could build a BlackBerry application that talked to a Domino Web Service in about 3 minutes.\nBeginning with BlackBerry Device Software 4.2, Research in Motion added the ability to connect to Web Services from a BlackBerry Java application (using JSR 172), so I added building a BlackBerry Java application to my set of demos. I then wrote a series of articles on this site that documented the whole process. Here are links to the articles:\n\nDomino &amp; BlackBerry Java Applications Part 1\nDomino &amp; BlackBerry Java Applications Part 2\nDomino &amp; BlackBerry Java Applications Part 2.5\nDomino &amp; BlackBerry Java Applications Part 3\n\nAfter I left Research in Motion, I continued to present at the same conferences and added the Midwest Lotus User Group (MWLUG) conference to my standard tour. Because of the Web Services capabilities of Microsoft Visual Studio, it was pretty easy to add a demo of a Windows Mobile application to my presentations as well.\nThe iPhone and Android platforms were released without the ability to connect to XML-based Web services, so I had to find a different way for those platforms to connect to Domino. Android includes the JSON libraries from json.org, and there were several versions of JSON libraries for the iPhone platform up there as well, so I decided I'd use REST and JSON to accommodate Android and iPhone. At Lotusphere 2010, while recovering from pneumonia, I added an Android demo to the presentation and was even able to show an almost complete (I never finished it) iPhone example as well. At the conference I promised I'd publish an article here demonstrating how I built the Android application, so here it begins (finally). This article is the first part of a new series that's all about how to use REST and JSON to mobilize Domino data on Android. There'll be two articles in this series here, plus I'll eventually publish an article in the View illustrating the iPhone application.\nThe Sample Application\nIn case you missed the first part of this series, the application we're building here allows a mobile user to lookup contacts in the Domino Directory. The assumption here is that most every Domino customer has some extra database of contacts and mobile users will need the ability to lookup contact information. This is the same process as demonstrated in the original series; it's just modified so it leverages JSON instead of Web Services.\nAbout REST\nREST stands for Representational State Transfer and essentially it's a form of Web Service where parameters for a request are sent on the URL to the server and the server's response is returned in the body of the HTTP response typically in XML or JSON format although it could be in any format. RESTful Web Services are much easier to use then XML Web Services since it's so much less work to call the service and there's much less overhead when the data is returned as JSON rather than XML.\nAbout JSON\nJSON stands for JavaScript Object Notation and it's a way of representing data in a textual format that's easy to parse and manipulate. To quote json.org (json.org):\n\n“JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.\nJSON is built on two structures:\n\n\nA collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.\n\n\nAn ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.\n\n\nThese are universal data structures. Virtually all modern programming languages support them in one form or another. It makes sense that a data format that is interchangeable with programming languages also be based on these structures.”\n\nIn JSON, an array looks like this:\n\nAnd an Object looks like this:\n\nYou'll see how these apply in the following section.\n*JSON Images shamelessly 'borrowed' from json.org.\nDesigning the JSON Agent\nIn the Web Services version of the agent I created for the BlackBerry and Windows Mobile ve",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "What does AT&T do",
  "date":"Sun Jan 16 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1295222400,
  "url":"/posts/2011/what-does-att-do/",
  "content":"Another great article surfaced recently about AT&amp;T and how it will be affected by Verizon getting the iPhone. The article is from PC World and it's called What does AT&amp;T to when Verizon Starts Selling iPhones. It does a really good job highlighting the things that AT&amp;T has done to deal with the network overload caused by iPhone users and at the same time prepare for Verizon getting the device as well.\nPeople are going to switch, but AT&amp;T's network has been built up to support the iPhone and, not mentioned much in many of the articles I've read, supports simultaneous voice and data. The Verizon iPhone, built on CDMA, is not going to be able to provide access to both voice and data. It's something AT&amp;T's network supports but Verizon doesn't support until it gets to LTE. Why Apple would release a CDMA phone instead of LTE doesn't make sense to me considering people aren't going to be happy not browsing the web while talking on the phone.\nWhen Apple comes out with a new version of the phone that runs LTE a few months later, Verizon customers will be dumping their CDMA phones and buying new LTE Phones. Good for Apple, Bad for Verizon customers.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "The Verizon iPhone",
  "date":"Sun Jan 16 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1295222400,
  "url":"/posts/2011/the-verizon-iphone/",
  "content":"I've said this for a long time now and I'm speaking for myself, NOT my employer: The best thing that can happen to AT&amp;T is for Verizon to get the iPhone. As I've written here before, Apple doesn't care about the network, they just don't. So, Verizon getting the iPhone is going to really show how good AT&amp;T's network really is.\nWhat's interesting is the &quot;Verizon Deal May Expose iPhone Flaws&quot; article in the New york Times. Like the wired article of last summer, it's a good, even, balanced &amp; impartial look at the iPhone. Some parts of the article that struck me as interesting (and true):\n\nYet for all that it offers, the iPhone has always been plagued by serious drawbacks. The “phone” part of the iPhone has never worked very well, dropping calls with annoying regularity. Even when the phone works, the sound quality is often substandard. You would think in an age when fewer people are using landlines this would matter. Apparently not.\n\nIf I'm on the phone with someone and the call drops, when they call back I always ask them &quot;you're on an iPhone, right?&quot; I don't get dropped calls on my BlackBerry, so if two phones are on the same network and the calls drop more frequently for the one phone vs. the other, which is it? The phone or the network?  It's the phone.\n\nMeanwhile, the iPhone's lack of a raised keyboard makes it next to impossible to do serious e-mailing. And users have to worry constantly about battery life; if they're not judicious, the iPhone's battery can be drained by noon.\n\nYeah, how good is a phone if the battery won't last past noon?\n\n“People so love their devices from Apple that they are willing to put up with the stupidities,” said Larry Keeley, president of the innovation and design firm Doblin. “For many users,” he added, “especially the ones Apple loves the most, the fact that the battery gets balky is how you convince yourself to get a new one.”\nMy oldest son, Amato, who is on my Verizon Wireless plan, told me recently that even though he was perfectly happy with his Android phone, if given the chance to switch to an iPhone, he would probably do it. “I can't even say why,” he said. “I don't even know if there is any real rationale behind that desire.”\n\nTrue, very true - People are going to buy one no matter how good it is (or isn't).\nWhy not support Verizon's 4g network? That one makes no sense - right after the launch of LTE for Verizon (although Verizon's implementation of LTE isn't 4g, not yet).  Check out the quote:\n\nAt the Verizon Wireless-iPhone extravaganza on Tuesday — in which the two companies announced that the iPhone 4 would run on Verizon Wireless's 3G network — Apple's chief operating officer, Timothy D. Cook, was asked why Apple wasn't going with the carrier's faster, newer 4G LTE network. Mr. Cook replied that doing so required “design compromises” that Apple was unwilling to make.\nThey never make design compromises at Apple. They make consumer compromises. Yet consumers have always been willing to overlook those compromises so they can claim they own some of the coolest products on the planet.\n\nI'm sticking with my BlackBerry, thank you. I use my iPhone for some apps (like the Sonos app) but for day to day business, nothing beats a BlackBerry.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Spam Tester",
  "date":"Tue Jan 11 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1294790400,
  "url":"/posts/2011/spam-tester/",
  "content":"I run a WordPress blog and setup the registration option so friends and family (especially my last remaining Aunt) can know when I post new items to the blog. I setup the system to notify me when someone registers and it's funny to see the different spammers register for the system. Usually the user name they enter doesn't look anything like the email address - that's usually a good clue for me that it's a spammer. You'd think that the user name someone selects would match their primary email address, but that's not what they usually do. I haven't tested this, but I'm sure the email addresses are bogus - too funny though how many of them end in .ru.\nYou've got to love it though when spammers register for your site and clearly identify themselves as spammers. Take a look at the following screen shot:\n\nThe person registered for the site and the email address they're using tells it like it is: someone testing some spamming software.\nWordPress has a pretty cool system that blocks spammers from posting stuff to your blog. I use dto use the Nucleus CMS for my blog and one time I had hundreds of spam comments on all sorts of areas in my blog. With WordPress, blocking those guys is automatic, you enable the module and it keeps the bad stuff out.\nYou'll notice that I'm not doing what most people do and spell spam with all capital letters. A lot of folks out there think Spam is an acronym when really all it is is a tasty breakfast meat. It's just a word, nothing to get all capitalized about.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Torch Refresh Weirdness",
  "date":"Mon Jan 10 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1294704000,
  "url":"/posts/2011/torch-refresh-weirdness/",
  "content":"I've been using the BlackBerry Torch 9800 since it came out (one of the benefits of working for AT&amp;T, you get new BlackBerry devices as soon as they come out). The first release was not ready for prime time, I had responsiveness issues and some pretty interesting ui weirdness. When the first maintenance release came out, most of the issues I'd encountered were resolved, and the Torch became an excellent device for me. I carry it as my primary device and have had very few issues with it.\nYesterday morning though, I went into my office to begin my work day and found that the Torch 9800 wasn't on.  I have it configured to turn itself off at 11 PM and back on again at 7 AM. It was after 8 and the device wasn't on. So, I poked and prodded it, but couldn't get it to come on. I had to pull the battery to get it to come on. Weird.\nLater in the day, I was trying to do something with it and it became unresponsive and hard to use. At one point, I was trying to do something and it took a while to catch up with what I was trying to do and it left itself in the state shown the following figure - weird.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Dashcode, Dashcode, Dashcoding away",
  "date":"Sun Jan 09 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1294617600,
  "url":"/posts/2011/dashcode-dashcode-dashcoding-away/",
  "content":"I spent some time over the holidays building some sample applications for my Lotusphere presentation. I finally got the time to spend some quality time with Dashcode and build a couple of applications that get their data from a Domino server. After some trials and tribulations I was finally able to get it to work - woohoo! \n\nDashcode is cool and now that most of the major smartphone players are all using the WebKit browser, applications written in Dashcode should (and I'm saying should - I haven't tested this yet) work on devices besides the iPhone and iPad. One of the things I learned while teaching myself Dashcode is that the documentation available from Apple is pretty horrible. I really struggled to learn how to do some of the things I wanted to do. Dashcode is so good at pointing to a data source and building a complete application that talks to the data source that Apple apparently decided it wasn't worth it to document any of the other aspects of the program. Disappointing.\nUntil recently there haven't been any books written about Dashcode. There were some that mentioned Dashcode, but none that were truly about Dashcode. Fortunately there's a new Dummies book on Dashcode. I ordered a copy and have been reading through it. I'm hoping I can find the time to finish it by Lotusphere, perhaps I'll enhance my demos a little bit and show a more sophisticated application than I originally planned. One of the things I'm planning for my Lotusphere session is to try to build a Dashcode application for Domino in less than a minute.  I'm going to see if I can quickly build the app while someone times me then I'll go back and show the complete, unhurried steps in the process. It will be fun.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Macintosh Woes",
  "date":"Tue Jan 04 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1294185600,
  "url":"/posts/2011/macintosh-woes/",
  "content":"I've been doing a lot of work on the Macintosh lately. My employer gave me a Windows laptop, but when I started doing more mobile development, they gave me a 17” MacBook as well.\nWhat's funny about using the Mac for me is how hard it's been for me. Not because I'm uncomfortable with the Macintosh or the Mac OS - I was an old Macintosh user, I used a Mac before I ever used an IBM PC. No, the issue for me is the keyboard.\nWhen I taught Novell and Lotus Notes classes, my server was always off in the corner of the classroom on a little table. Because of the size of the table, I never had much room for a mouse, so I got very (very, very) used to using the keyboard to get a lot of things accomplished.\nOn the Macintosh, many of the keys I'm looking for are just missing.\nI'm an INSert key guy. Copying is Ctrl-INSert. On the BlackBerry Simulators, you use the INSert key to bring up the BlackBerry menu.\nI also miss the End key and the Home key. As I navigate around on a web site or in a word processor, I used those keys to get to the top of a document or to the end of a line.\nAlso frustrating is the loss of the delete key. In word or in other applications, I'm constantly deleting the word to the right of the cursor using Crtl-Del.\nI'm also finding that I have difficulty moving the cursor from word to word in the word processor of choice. I'm so used to using Crtl plus the arrow keys to skip words.  I know you can still do some of these things with corresponding keys on the Mac keyboard, but I find that the implementation of some of these features is inconsistent between applications. Ugh!\nI'm excitedly waiting for Henge Docks to release their dock for the Macbook Pro 17” - once that happens, I can plug this thing into my KVM and have a full IBM keyboard to use.  I've been waiting for months and there's been little progress.  Not sure why they're not releasing products.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Lotusphere 2011 Session",
  "date":"Sun Jan 02 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1294012800,
  "url":"/posts/2011/lotusphere-2011-session/",
  "content":"My Lotusphere 2011 session with Rob Wunderlich is BP209 and entitled Delivering Domino to Mobile Devices: More Stupid Tricks. The session is scheduled for Tuesday, February 1, 2011 at 1:30 PM. \nLast year they scheduled a repeat session, I guess that won't be the case for this year.  Come see us and say hello!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "BlackBerry Widgets",
  "date":"Sun Jan 02 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1294012800,
  "url":"/posts/2011/blackberry-widgets/",
  "content":"I spent some time this weekend working with the BlackBerry Widget (now inappropriately called WebWorks) development tools. They're pretty cool. I've never built web applications designed to run on device (rather than on a server) and didn't have any real experience with much client-side JavaScript, but it real easy after Scott Good kindly provided me with some sample code to work with. I created a couple of applications right away and learned a bunch while I did it. \nOne of the things I've done on this site is write about how to build Web Services in Domino so you can consume them from mobile device applications. The Android and iPhone platforms don't support XML-based web services directly, so I had to build a JSON agent (a RESTful web service) for those platforms. Ultimately I need to document that work, I promised to at last year's Lotusphere, but haven't done it yet, sorry. Anyway, for the widget applications (and some work I have been doing in Dashcode) I leveraged those very same RESTful web services to build the application shown below. This is one of the application's I'll be showing at Lotusphere 2011.\n\nI've also been working on using Dashcode to build mobile applications that talk to Domino data sources, I've created a sample application (shown below) that I'll also be showing at Lotusphere 2011.\n\nAdditionally, my publisher has been asking for an update to BlackBerry Development Fundamentals. One of the things that had been missing from the book is coverage for BlackBerry Widgets and the BlackBerry Push API's. Both of those technologies were released after my book was finished and I'd like to update the book to include them. Who knows, perhaps I will even put together a widget book. Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Dreaming in Code",
  "date":"Sat Jan 01 2011 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1293926400,
  "url":"/posts/2011/dreaming-in-code/",
  "content":"I've been interested in Chandler for a long time now. Chandler, if you don't know about it, is an open source project created by Mitch Kapor (one of the founders of Lotus). Chandler was supposed to change the world of calendaring in personal information management, but I don't think it ever did.\nFor Christmas, my boss gave me a copy of Dreaming in Code: Two Dozen Programmers, Three Years, 4,732 Bugs, and One Quest for Transcendent Software a book that chronicled the creation of the project and associated program. The book was on my Amazon wish list, so it was great that my boss picked it up for me. I'd heard that the book was a hard read and being almost finished with it, I see why. The author tried to tell the story, but spent way too much time talking about other stuff that wasn't really related to what was happening with Chandler. It's like he wanted to write a book about this cool open source project, but wanted to write the book for non-developers. There are sections and chapters dedicated to providing some background on the technology and problems faced by development organization – I guess there to help the non-developer understand the background. Unfortunately, I'm really not sure why a non-developer would be interested in the book.\nI downloaded the latest version of Chandler the other day and I'm going to poke and prod at it over the next few weeks. I just ordered some parts for a new PC build, so I'll setup a little sandbox and see what the program has to offer. I need to find a calendar I can share with my wife and ultimately my kids as well (as they get older). I probably need to take a look at Google Calendar as well.\nI'll let you know my thoughts on Chandler when I finish my evaluation.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Getting Ready for Lotusphere 2011",
  "date":"Mon Dec 27 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1293494400,
  "url":"/posts/2010/getting-ready-for-lotusphere-2011/",
  "content":"In preparation for Lotusphere 2011, I've been working on some demos for the session Rob Wunderlich and I will be giving at next year's conference. One of the things I want to be able to show is how to use Apple's Dashcode web application development tool to access Notes data plus how to build a BlackBerry Widget that does the same thing.\nI spent some time over the last week or so poking and prodding at Dashcode and was able (finally) to get it working this morning. It's pretty easy to build an application that talks to a Notes database, but Dashcode does something to the URL you enter that breaks it when you actually try to deploy the application in the wild. I spent hours on it this morning and just couldn't figure it out. I tried all sorts of different things trying to get my data to show up in the application. It was only when I looked over on my Domino server that I noticed that there was an error on the console. A simple change and all of a sudden it worked.\nTo learn more, come to our session at Lotusphere!  Stay tuned for details.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Perfecto Mobile",
  "date":"Tue Dec 21 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1292976000,
  "url":"/posts/2010/perfecto-mobile/",
  "content":"I've been getting some briefings lately from Perfecto Mobile regarding their mobile application testing capabilities. I'd known a little bit about the market and identified some of the players in BlackBerry Development Fundamentals, but really didn't have a good idea of how it worked. From the briefings I learned more about the technology behind it and it's pretty cool.\nThey essentially place a bunch of active mobile devices in cradles in a data center then connect to them via a USB cable. Through a web interface you as a customer have access to, you can install applications on a device plus pull logs and other information from the device and interact with it. What surprised me was that they also offer a scripting language you can use to automate testing on the device; pretty cool. I still need to play with this directly, but as I understand it you can write scripts that poke and prod at the device, which I expected they could do through interfacing with the keyboard buffer and other API's the device manufacturers provide. You can even swipe through menus and click menu items , buttons and application icons. Again, I don't have all of the details, but apparently you can provide an image that the scipt uses to identify a menu item or application icon to click - as your script moves things around on the device, you can configure it to click when it finds the particular item you're looking for. So, if a menu item or application's icon position changes depending on what other applications are installed on the device, your script can still find it.\nI'll be taking a real look at this solution after the holidays and I'll let you know what I find out.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Sizing Windows in Windows",
  "date":"Thu Dec 16 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1292544000,
  "url":"/posts/2010/sizing-windows-in-windows/",
  "content":"In all of the different things I do, I often spend a lot of time writing about computer-related topics. With my book, magazine articles, conference presentations and in my regular day to day job activities, I find myself needing screen shots of Windows computer screens. While it's really easy to grab screen shots in Widows (I'm a huge fan of Snagit From TechSmith Corporation) it's not always easy to set the size of the window you're taking a snapshot of. When working with a full screen window, it's not that big of a deal, but I've got a huge monitor (at least it was huge 5 years ago when I bought it) so full size screen shots won't fit in most mediums I publish in.\nA long time ago I went looking for a utility I could use to set the size of windows in Windows in order to be able to take screen shots at a more medium friendly size. I came across a free utility called Sizer from Brian Apps that does the job for me (almost - I'll explain later).\nWhen you install Sizer, it installs an application that, when launched, places an icon in the Windows system tray (shown in Figure 1 with an orange box around it) and also enables a context menu that you (shown in Figure 3) can use to resize any window.\n\nFigure 1 – Sizer System Tray Icon\nConfiguring the Program\nBefore you can use the program, you need to configure the different window sizes you want to be available in the program. If you right-click the Sizer system tray icon and select 'Configure Sizer…' from the menu that appears, you will be presented with a screen similar to the one shown in Figure 2.\n\nFigure 2 – Sizer Configuration Dialog\nFrom this dialog, you configure the different window sizes you wish to be able to use when resizing windows. You can set specific window dimensions or use the program to set a specific window position.  When you have the settings configured the way you want them, click the OK button and you're ready to go.\nUsing the Program\nTo resize the window, right click on the window's title bar and you will be presented with a menu similar to the one shown in Figure 3. At this point, you can select one of the pre-configured window sizes and Sizer will resize the window to the selected dimensions, keeping the window's upper left corner in the current position (unless you selected an option that also moves the window).\n\nFigure 3\nThe program works pretty well and I've used it for many, many years now. It's proven to be very useful and well worth the cost (it's free!) What bothers me though is that some windows won't display the context menu. The Windows Explorer application in Vista 64 won't display the context menu when you right-click on the title bar. It's not really a problem though since I can still select the window and resize it by right-clicking on the system tray icon then picking a window dimension from the pre-configured list.\nIf you're looking for a way to resize windows quickly and easily – give this free utility a try.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "It is the BlackBerry Browser's Fault",
  "date":"Wed Nov 17 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1290038400,
  "url":"/posts/2010/blackberry-browser-fault/",
  "content":"I'm regularly asked to help suggest a solution for customer having problems using the BlackBerry browser to access certain sites or applications. It's a common problem and rarely actually a problem with the BlackBerry browser. I thought I'd spend some time to talk about what's going on here and hopefully make you understand what's usually going on.\nThe BlackBerry Browser\nOne of the things Research In Motion gets dinged on regularly is the browser, but it's important to note that Research In Motion worked deliberately to make the BlackBerry Browser small, fast and secure. What people see as faults in the BlackBerry Browser are in reality just the side effect of Research In Motion designing the browser for mobile web sites, NOT for viewing desktop web sites. Expecting that mobile web developers would build text-based web sites with limited flash (pun intended) for mobile users, they built a browser specifically for that need.\nThe BlackBerry browser is a standard browser. All of the standard web technologies you'd expect to be supported are supported. There might be a delay in implementation of a particular technology, such as Adobe Flash for example, but Research In Motion generally implements anything they think regular, everyday web sites use. Recognizing that the world has changed, and the market expects web sites viewed on a mobile device to look and feel like the desktop version (which they shouldn't in my opinion), Research In Motion acquired Torch Mobile and implemented Apple's WebKit web rendering engine in BlackBerry Device Software 6.0.\nWeb Site Issues\nSo, now that we have a little background on the BlackBerry Browser, let's dig into some of the problems you'll encounter when accessing web applications on a BlackBerry Browser. I'm going to focus primarily on commercial web applications that companies will often be using on their desktop computers and all of a sudden want to extend those applications to mobile devices. The same problems can be encountered in home grown web applications, but generally those are usually simpler applications and aren't doing weird things (I'll explain soon).\nActiveX Controls\nThe biggest problem that plagues web applications running on mobile devices is that many commercial applications utilize ActiveX controls to provide some interesting functionality for the application. ActiveX controls are essentially Windows programs that Microsoft has allowed web developers to wedge into their applications. They provide more interesting looking forms, more dynamic content and much of the same things Java Applets provided web users back in the 90's. The only difference is that they're written using Microsoft's technologies rather than industry standards.\nThe problem with ActiveX controls (actually, there's many – but I'm not going to get into that here) is that since they're a Microsoft technology, they only work in Microsoft's browser (Internet Explorer - IE). They leverage specific hooks Microsoft has implemented in Internet Explorer (and essentially no other browsers) and allow developers to do some pretty cool things.\nThe problem that affects mobile users is that IE is not available on anything but a device running Windows Mobile (or the new Windows Phone) operating systems.\nIf you have a web application that ONLY works on Internet Explorer and you encounter problems running the application on a BlackBerry, you need to ask some questions.\n\nDoes the application leverage ActiveX controls?\n\nIf the answer is yes, then the application is never going to work in the BlackBerry Browser as is. It would have to be rewritten to work on other browsers. When your customer or the application's end users start to complain about this limitation, you'll need to ask them another question:\n\nFor desktop users, does it work on any other browser than Internet Explorer? Something like Firefox, Google Chrome or Opera?\n\nIf the answer is no, then how could they be complaining that it doesn't work on the BlackBerry when it clearly doesn't work on anything except IE? If the application was coded to IE, then it either uses specific features of IE (and won't therefore work on a BlackBerry) or it was written to address specific limitations within IE (and won't therefore work on a BlackBerry either). You're stuck and shouldn't spend much time trying to fix something that can't be fixed.\nIf the answer to the last question was yes, then perhaps you have some more work to do. If the app works on most desktop browsers but not the BlackBerry Browser, then there could be something else going on (although still I'm not willing to blame the BlackBerry Browser for this) and you'll need to look at the next two sections for more information.\nBrowser Detection\nIt's hard for a lot of people to recognize this, but the browser a browser and if an application you're running uses standard web technologies such as HTML, JavaScript and CSS, it should work just fine anywhere. When you encounter a problem where a web application w",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Conference Application",
  "date":"Mon Sep 27 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1285632000,
  "url":"/posts/2010/blackberry-conference-application/",
  "content":"At the BlackBerry Developer conference this year Research In Motion waited until the very last minute to announce availability of the conference application for this year's conference. Last year's application was written by Sweet Caesar and, while functional, it was hard to use – they'd tried too hard to build in all sorts of screen effects and because of it the application was unusable. I wrote about it in my 'What were they thinking series'.\nAnyway, for this year's conference Research In Motion hired Pyxis Mobile to build the application. It's based on Pyxis Mobile Enterprise Application Platform which allows a company to build one application and run it on multiple mobile platforms.\nWhen Pyxis built the application, they didn't go overboard with the screen transitions, they just built a simple application that got the job done. Just what was needed. Here's a screen shot of the application – the only issue I have with it so far is that there's not enough space between the menu items – on a touch screen device it's hard to select the right menu item, I always seem to select the one I don't want.\n\nIn every session today they reminded everyone to fill out their session evaluations – either on the conference's web site or using the mobile application. Interestingly enough, if you look at the screen shot below, you'll see that apparently Pyxis didn't actually include that feature in their application.\n\nBecause of the way the Pyxis platform works, it's very easy for them to add the feature to the application tonight and automatically deploy it to all of us tomorrow morning. When the application starts, it checks on the server for an updated version of the application and downloads it as needed.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry App Problem with 6.0",
  "date":"Mon Sep 27 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1285632000,
  "url":"/posts/2010/blackberry-app-problem-with-6.0/",
  "content":"At the BlackBerry Developer conference opening session yesterday they highlighted a bunch of consumer applications that they, RIM, thought were interesting, ground breaking or at least fun. What I noticed though was that many of them were not available yet for a device running BlackBerry Device Software 6.0. In the session they demonstrated the dictionary.com, not available yet for BlackBerry 6.0. They highlighted the things Xobni has done (cool product), not yet available for BlackBerry 6.0. The amazon app? Not available in the App World (it's available for download directly, but it's not where the other standard BlackBerry apps can be found).\nApparently moving an application to Device Software 6 is more problematic than expected. \nAnother thing that was very clear yesterday was that RIM is solely focused on consumer devices and consumer applications. The BlackBerry Playbook is for Enterprises mostly, so that's an exception. 90% of what they talked about yesterday in the opening session, except for the Playbook, was focused entirely on consumer-focused application.\nWith the new BlackBerry Messenger integration capabilities and the libraries for connecting to Twitter and Facebook, their intention is clear - make it as easy as possible for developers to build social networking into their apps. The question I have though is when is enough enough? How many applications do I need on my device that integrate with Twitter and Facebook? Do I really need that? I have a Facebook app, I have a Twitter app, why do I need all of my other applications to interface with those services? What's going to be happening soon (and has probably already started to happen) is that users will have too many applications. The BlackBerry, iPhone and other platforms can supported a limited number of applications - before long you'll be deleting stuff you don't use that often to make room. When all of my apps share common features, like interfacing with Twitter or Facebook, how do I then distinguish between separate apps?\nOne of the examples Mike Kirkup showed in the session was a hardware dongle you could attach to your car keys to a BlackBerry application can track them. One of the differentiating features he showed was that the tracking application integrated with Facebook and Twitter. That way you can quickly let all of your friends and followers know when you've lost your keys. Seriously? How is that important? How often do you lose your keys? Am I going to tweet when I lost my keys? Possibly, just in case I was with some of my followers recently (when I last saw my keys) Post on Facebook about it? Possibly, but why don't I just use my Facebook or Twitter apps for that?  Even better use an aggregator to do it, but why does that functionality need to also be in the key finder app?\nPeople are going to quickly realize that a big percentage of their device memory is being taken up by features of many applications that duplicate each other. Where's the fun in that?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "The BlackBerry BlackPad",
  "date":"Sat Sep 25 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1285459200,
  "url":"/posts/2010/the-blackberry-blackpad/",
  "content":"OK, I'm convinced. RIM's going to announce the BlackBerry BlackPad tomorrow. There were rumors of this last week, but you know how rumors are. What's synching it for me is how coy my RIM contacts are. Tomorrow starts the BlackBerry Developer Conference, and it makes sense that if you're going to bring to market a new tablet device and run it on a new OS (as the rumors say) then you're probably going to make it available to developers (like me) first. I'm thinking, but I'm probably wrong, that I'm going to leave the event with one. Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Additional View Articles",
  "date":"Sat Sep 25 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1285459200,
  "url":"/posts/2010/additional-view-articles/",
  "content":"I just finished my second and third articles for the View (eview.com). The second article is an introduction to mobile development for Domino and focuses on web development. The third article extends the second and talks about native mobile development for Domino and includes Hybrid and MEAP applications. It was a lot of fun to write these articles. I started with an idea and as I started writing, the article got bigger and bigger and bigger. When I submitted it, my editor immediately started talking about splitting it into two parts. This was good because it allowed me to extend the second part and make it more complete. As I wrapped the first version up, I started omitting content because I knew it was going to be too long. Splitting it allowed me to make it much more complete.\nI'm off to the BlackBerry Developer Conference in San Francisco this week. When I get back, I hope to put the finishing touches on a fourth article, one that covers in details how to mobilize Domino applications using the Kryos Velocity Designer for Lotus Domino. Stay tuned for that one.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "View Article on Mobile Domino Development",
  "date":"Thu Sep 23 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1285286400,
  "url":"/posts/2010/view-article-on-mobile-domino-development/",
  "content":"I'm just putting the final touches on an article I wrote for the View.The article covers options for mobile development using Domino. The article ended up being so long, that they had to split it into two parts. Part 1 highlights web development options and part 2 covers native and mobile platform (MEAP) applications. Essentially this will be the second (and third) article in the series that covers everything related to mobilizing Lotus Domino data.\nI'm also doing an evaluation of the Kryos Velocity platform for Domino (Velocity Designer for Lotus Domino) and am almost finished with a review of the product that will hopefully find its way into a future issue of the View.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "BlackBerry Developer Conference 2010",
  "date":"Tue Sep 21 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1285113600,
  "url":"/posts/2010/blackberry-developer-conference-2010/",
  "content":"My publisher has arranged to have copies of BlackBerry Development Fundamentals on sale at the BlackBerry Developer Conference in San Francisco the week of September 26th, 2010. This year, there's a special book store being setup at the conference and they'll be raffling off several free copies of the book during the conference. They've also scheduled a book signing for Tuesday afternoon between 12 and 1 (during lunch), look me up if you're going to be there.\nMy editor brought a whole bunch of books to the conference last year and we sold out way before the book signing they scheduled for the last day of the conference. Whenever I had a spare minute, I'd hang out where he was selling books, just to see how things were going, and I ended up signing many of the books anyway. I've got to remember to bring my special book signing pen with me to the conference.\nOne of the reasons he came to the conference last year was to look around for people who were interested in writing BlackBerry books. If you have an idea for a book, let me know and I'll introduce you to my publisher. I'm going to spend the next few weeks mapping out an update to BlackBerry Development Fundamentals, lots of things have changed in the BlackBerry development world since the book was published (widgets, the UI builder and more) and it's probably time for an update. I'm also tossing around an idea for another book and I've already discussed the concept with my editor. I told my wife I wouldn't write another book until I'd taken off as much time as I spent writing my last one (my first book didn't take that much time, but the second one was a killer) and it's about that time. I had so much fun writing (and became such a better writer because of it) and I miss it.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Amusement Park Marketing and Technology",
  "date":"Fri Sep 10 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1284163200,
  "url":"/posts/2010/amusement-park-marketing-and-technology/",
  "content":"We went to a local amusement park today, just about 20 miles from here. I noticed two interesting things while we were at the park. One was an interesting marketing trick and another was an interesting use of technology.\nLiving in North Carolina, we get more nice weather than we were use to in Northeastern Ohio. I loved Cedar Point, but never seemed to make it there. With the nicer weather here, I can go from March to November, much longer than I could at Cedar Point.\nAs we walked around the park, they repeatedly made announcements indicating that we could trade in today's admission price against a season pass for the 2011. Regular price was about $50 (plus $10 for parking) and with a discount received by delivering one canned Coke product for each of us, we were able to enter the park for $35 each. Expensive for a fall day, but not a bad deal considering it would have been $50 otherwise ($200 for the 4 of us). The additional cost for a season pass for next year was $30 for each of us. That meant, for less than the cost of admission today, we get an entire season of free admission plus free parking. Not a bad deal.\nThe acquisition price for a new season pass holder must be pretty high or sales must be pretty low for them to offer this deal. We know we're going to go at least once next year, so no matter what we've saved money on this deal. Nice.\nAs you probably know, they take pictures everywhere at the park and try to get you to buy them. When we rode the first ride that generated a picture, it was interesting to see them offer putting the photo on a USB memory drive for the same price as a printed picture. Nice idea – I get an electronic copy of the photo and don't have to carry a print with me everywhere I go.\nThere's got to be a mobile application in here somewhere.\nI'm thinking that an amusement park could offer customers a mobile application to help make this even easier. You download a free copy of the mobile application before going to the park then enter in your credit card information. As you finish the ride and get funneled through the area to view the photos that were just taken, you can acquire the photo directly from your mobile phone; nothing to carry around the remainder of the day. When you find a picture you like, you enter the ride number then the photo number. Your credit card could be charged directly and you could even be offered a discount by using the application. It would certainly cost the amusement park less money since there'd be no printing or copying files to a memory stick that would just get lost. The photo could be emailed to the device, sent via MMS or even downloaded directly to the application running on the phone.\nYeah, that would be something I would be interested in. I'd probably buy more photos.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "BlackBerry Web Clip",
  "date":"Thu Aug 19 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1282262400,
  "url":"/posts/2010/blackberry-web-clip/",
  "content":"I noticed something interesting this morning while playing with my new BlackBerry Torch 9800. I was checking in for a flight home and thought I'd try the new boarding pass on the mobile device thing. I finished my check-in and had the airline send the boarding pass to my work email account. I opened the message and clicked on the link to bring up the mobile boarding pass. It's a web page and the page had some instructions for how to make it easy to load the page while at the airport. I didn't want to bookmark this page, but I did want to try to save it locally on my device. As I opened the BlackBerry menu, I noticed a new option called 'Add to Home Screen' (shown in the following figure). Of course, that's what I wanted to do, so I selected that option.\n\nAfter it saved, I took a look at the device home screen (shown below) and noticed there was a little icon representing the page I'd saved (as CO Boarding Pass). The device even tried to make the icon look like the page it referred to. Pretty cool. It's a great feature and, once again, the BlackBerry can do the same things the iPhone can do (plus run any application in the background with great battery life).\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Books",
  "date":"Wed Aug 04 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1280966400,
  "url":"/posts/2010/blackberry-books/",
  "content":"I started BlackBerry Development Fundamentals December 1, 2008 and it was published November 9, 2009. Because my publisher is involved with Safari Books Online, an early draft of my book went online there in June '09 so I felt comfortable saying my book was the 'first' BlackBerry Development book on the market.Craig Johnston published Professional BlackBerry in 2005, but although it was touted as a BlackBerry development book, there really wasn't much 'development' in it.\nAbout the same time BlackBerry Development Fundamentals, my wife found a reference on the Internet for Anthony Rizk's Beginning BlackBerry Development and the race was on to see which book 'published' first. Anthony and I both launched our books at the BlackBerry Developer Conference in San Jose in November of 2009 - He gave away a few copies of his book on the last day of the conference and my publisher had 75 copies on hand, setup a booth and had a book signing. It was a lot of fun.\nI regularly monitored Amazon to see what other BlackBerry-related books were scheduled to be released and saw that Apress (the publisher of Anthony's book) had several titles in the works. Eventually Wrox got into the game and added their 'Professional Blackberry Java Development by David Williams to the book listing on Amazon. Of course I've read all of the other BlackBerry development books - I've even written reviews of them for Doctor Dobb's Journal (if I can only get them published), so I had to order this one so I could see what I could learn. The book was supposed to be published in February, but never did. Back in May, I received a notification from amazon that they were unable to acquire the book for me. Apparently Wrox isn't getting back into the BlackBerry book market.\nBlackBerry Development Fundamentals came out right before RIM finalized Widgets and some other technologies, but since I actually finished the book months before it was published, it was still too beta for me to include in the manuscript. I intended to go back and do an update around Widgets and App World and perhaps with RIM's announcement of BlackBerry Device Software 6.0 I will do some digging and update the book. We'll see.\nIf you hear of any new BlackBerry books, let me know. I like to read them to see what new things I can learn and ultimately I want to get back to updating my BlackBerry Books web site.  Right now I'm reviewing a new BlackBerry Enterprise Server book for Packt publishing.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Telepresence",
  "date":"Sat Jul 24 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1280016000,
  "url":"/posts/2010/telepresence/",
  "content":"Attended my first Telepresence meeting last week. I was meeting with a customer in a local office, but some participants were also in Chicago. We walked into this room with an oval conference table and three monitors sitting on the far half of the table. A few minutes later, people arrived in the room in Chicago, turned on the lights and started interacting with us. It was so interesting, being able to make eye contact with people you are working with across the country.\nOf funny note though was what happened halfway through the meeting. The person 'across' from me wrote something down and passed it to the person next to him. They muted the phone and started laughing about something (without even looking at us). We could tell they weren't listening to us, but kept talking along and they soon rejoined the conversation. That very well could have happened in any conference call I attended, but with this technology we could easily tell they were doing it. I wonder, since they knew we were seeing them, why they even did it.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Customer Conversations & The Lost BlackBerry Mindshare",
  "date":"Fri Jul 23 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1279929600,
  "url":"/posts/2010/lost-blackberry-mindshare/",
  "content":"Customer Conversations &amp; The Lost BlackBerry Mindshare\nI was meeting with some executives of a half a billion dollar company last week and was struck by how Research In Motion's reputation was being tarnished due to lack of understanding about the BlackBerry platform's capabilities. The company employees carry BlackBerry devices and most of the company's customers carry BlackBerry devices, but the company is creating an iPhone application.\nThe CEO carries a BlackBerry but he also has an iPhone (for personal use I guess). During our conversation, he explained how he has a whole bunch of applications on his iPhone and uses them all the time. When I asked him if he had any applications on his BlackBerry, he responded by saying that he didn't know he could have applications on his BlackBerry. Of course, being a BlackBerry guy, I immediately showed him how to install the BlackBerry App World application on his device and how to search for applications, download them and so on. He was ecstatic and apparently played with his BlackBerry all throughout the meeting that followed ours.\nAfter that, I spent some time with the Director of Corporate Communications. As he described what he did and what he expected from us, he (carrying a BlackBerry mind you) explained how he understood that the iPhone really delivered a great user experience. He went on to describe how simple things he needed to do on his BlackBerry were 'Hooooorrible!'  Of course, being a BlackBerry guy, I waited as long as I could before asking him what types of things he was doing that was causing him so much grief. He explained that when getting his Yahoo! email, performance is horrible and he constantly received a 'retrieving data' message on the bottom of the screen while waiting for the mail to load. Of course from hearing that I immediately knew that he was accessing his Yahoo! mail using the browser – and of course he was going to have a poor experience.\nI immediately explained to him how he could have one corporate and up to 10 personal email accounts delivering mail into his messaging application on his device. I explained how the browser would always be a horrible way to get his mail on a BlackBerry and that was why Research In Motion was so accommodating when it came to mail. I pointed him to https://att.com/blackberrystart and explained how he could configure his personal mail and interact with it in exactly the same way he worked with his corporate mail, though an application rather than a web browser. I pulled out my device and showed how I had a special Mail folder and listed each of my personal mail icons there.  I'm not sure he followed my advice, I sure hope so since it never makes sense to access your mail via the BlackBerry browser.\nWhat's sad though is how everyone assumes that the iPhone experience will be excellent and how certain that the BlackBerry experience is poor. In reality, in both of these cases it was the user's lack of understanding of what they could do with the device that was tarnishing their experience. No matter what Apple does, the BlackBerry mail experience will always be superior. BlackBerry was built on mail and security and there's no way anyone can catch up.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Lotusphere 2010 Presentation Posted",
  "date":"Fri Jul 09 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1278720000,
  "url":"/posts/2010/lotusphere-2010-presentation-posted/",
  "content":"Google told me this morning that someone posted my AD114 slide decks from Lotusphere 2010 on a slide sharing web site: here. The presentation covers how to build rich client applications that talk to Lotus Domino databases. It's something I've been presenting on for several years now (at Lotusphere and the View conferences). What I've done is build a Domino Web Service then showed how to build BlackBerry and Windows Mobile clients that talk to the database. This year I added Android (for Lotusphere) and iPhone (for the View conference) versions of the application although I wasn't able to get the complete iPhone application working in time for the conference.\nI've written about the web service and the BlackBerry application here - there's a series of 4 articles that cover it in detail. I'm in the process of writing up the Windows Mobile application (which I'll post here as soon as my back gets better) and I'll add Android soon as well.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "BlackBerry Device Software 6.0",
  "date":"Tue Jun 22 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1277251200,
  "url":"/posts/2010/blackberry-device-software-6.0/",
  "content":"08/08/2010: When I wrote the following post RIM was calling the new version of the Device Software 'BlackBerry 6' and I confirmed with Mike Kirkup (the Director of RIM's ISV Alliances team) before writing the post that it was still being called BlackBerry Device Software 6.  Apparently between the time I wrote it and the release of the device, RIM changed their minds and started calling it BlackBerry 6 OS.  They've NEVER called it the OS previously - but perhaps since Apple does it they thought they'd do the same.\nI've been trying not to vent too much here anymore. I realized I was being pretty negative and vowed to publish articles that might really interest people. Unfortunately I can't pass on the opportunity to comment about the market's response to BlackBerry Device Software 6.0.\nFor BoxTone, Vox Mobile and all of those other companies that have hosted webinars on what happened at WES and for BlackBerry Cool and all of those other sites publishing news about BlackBerry - it's NOT called BlackBerry OS 6, it's BlackBerry Device Software 6. Just to make sure I didn't miss Research In Motion changing what they called it, I confirmed with the ISV team last week that it's called BlackBerry Device Software 6.\nThe BlackBerry Device Software is the suite of applications that provides the UI and applications the user interacts with on a BlackBerry device. The BlackBerry OS runs underneath the BlackBerry Device Software and provides the OS kernel and a suite of services (low-level routines) that are available to other applications. The BlackBerry Device Software is likely (although I haven't confirmed this) written in Java and the BlackBerry OS would likely be written in the native machine language for the device (processor). The two work together, but they're very different things.\nFirst of all, the developer really can't code to the OS, he or she codes to the BlackBerry Device Software and the Device Software interfaces with the OS at some lower level. When Research In Motion releases the Java development tools – they release them in conjunction with a BlackBerry Device Software release, not an OS release. It's the libraries published through the BlackBerry Device Software that a developer uses to build an application.\nIf you take a look at the screen shot that follows, you'll see that my BlackBerry Bold 9700 is running BlackBerry Device Software 5.0.0.405 (basically BlackBerry Device Software 5.0) and Platform 5.1.0.112. The platform then is the BlackBerry OS version.\n\nIf you look at this and think about what's coming out in the next month or so, you should expect then that the above screen for a yet to be announced device would show v6.0.0.x (or something like that) for the BlackBerry Device Software and most likely a Platform of 5.2.x.x.x (which is the device OS).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Writing for the View",
  "date":"Tue Jun 15 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1276646400,
  "url":"/posts/2010/writing-for-the-view/",
  "content":"I was excited when The View asked me to be a technical advisor for the publication. As a long time Lotus Domino developer and more recently being heavily involved with mobile development, I am excited to have another forum where I can talk technical about both. I've written my first article and will soon be starting on another - look for the first article to be published soon (hopefully).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Internet Learning",
  "date":"Sun Jun 13 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1276473600,
  "url":"/posts/2010/internet-learning/",
  "content":"I've been reading Wired Magazine (wired.com) since issue #3. I read about a lot of really cool technology there before I read about it anywhere else. Over the years, they've kinda changed their target audience – they still write about tech, but it's really targeted at people much younger than me.\nI still enjoy reading it although in these 18 years, I've still NEVER read any of the interviews they do. They always seem to interview people I have never heard of and even the short parts of some I've looked at, they never seem to look interesting.\nIn last month's issue, there was a very interesting article by Nicholas Carr called The Web Shatters Focus, Rewires Brains (https://wired.com/magazine/2010/05/ff_nicholas_carr/). Nicholas was the guy who wrote years ago about whether IT Mattered (https://nicholasgcarr.com/articles/matter.html) that apparently got a lot of people stirred up.\nAnyway, in this article in Wired, Nicholas published an article adopted from his upcoming book called “The Shallows: What the Internet Is Doing to Our Brains.” It provided some analysis of basically how the Internet is affecting us and our ability to pay attention to things has been changed because of it. What struck me was the following paragraph:\n\nIn a study published in the journal Media Psychology, researchers had more than 100 volunteers watch a presentation about the country of Mali, played through a Web browser. Some watched a text-only version. Others watched a version that incorporated video. Afterward, the subjects were quizzed on the material. Compared to the multimedia viewers, the text-only viewers answered significantly more questions correctly; they also found the presentation to be more interesting, more educational, more understandable, and more enjoyable.\n\nWhat's interesting about this is that everywhere you turn, regular classroom instruction and even books &amp; magazines are being replaced by electronic versions of themselves. My sister in law was visiting this week and she indicated that her school system has online training that she uses any time she wants to remember how to use a feature of the software she uses in her classroom. Working for AT&amp;T, there's so much required education that my employer provides us and it's all online. These companies are providing online education, but at the same time, the way some of it is presented actually makes it harder for us to absorb. Dedicated, closed training systems are better – but according to the article (and assumedly Carr's book) when we access content on web sites (with advertisements and links to other references) it's actually harder for us to learn.\nOne of two things are going to happen – nothing's going to change and we'll find ourselves having to work harder in order to be able to absorb what we're reading online or somehow web sites will become less cluttered and we'll stop linking everywhere (notice I've linked to two external sources in this article!) in order to make it easier for our readers.\nI wonder how this problem gets fixed.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Writing a Book, Part 4 – Fixing File Synchronization Errors",
  "date":"Wed May 19 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1274313600,
  "url":"/posts/2010/writing-a-book-part-4-fixing-file-synchronization-errors/",
  "content":"OK, here's final article in the series. So far I've talked about the method I used to backup my manuscript files through every part of the editing process and I've covered how I synchronized the files between my laptop and desktop computers as I went. In today's installment, I'm going to address a problem I created by synchronizing the files between systems. It caught me by surprise several times and forced me to make changes to how I managed the files. Ultimately it's the reason I decided to write the article series.\nAs I worked through the manuscript, I regularly moved things around within the chapters. I would reorder chapters as I worked through them to get the right order (Research In Motion never, ever, agreed with the placement of chapter 3) and I would rework the order of the content within the chapters as well. On top of all that, as I neared completion of the manuscript and started seeing how long it was going to be (it was approaching 600 pages and I only had a contract for a 400 page book) my editor started whacking images (a lot of them) in order to get the book within the budgeted size.\nAnyway, one of the things I noticed when I started giving my editor updated copies of each chapter was that the image files for the chapter were getting overwritten with different (wrong) image files. I scratched my head for a while then finally figured out what was going on.\nBefore I tell you what happened, I have to give you a little background. My publisher required that the manuscript be delivered using a particular Word template and a special naming convention for all files. The chapter content would be in a document named using the author's initials and the chapter number. So, for my book, the chapter files were called JMW01, JMW02, JMW03, and so on. Image files used in the chapter would be named in a similar manner – in this case, it was chapter file name plus an underscore and the sequential image number. So, using the previous example as a guide, the image files for the chapter would be named JMW01_01.jpg, JMW01_02.png, JMW01_03.jpg and so on. It allows for a very structured arrangement for the chapter files and I'm sure saves the editor and production people a lot of time and saved them from extra work trying to make sure they have all the image files required for the book.\nNow that you understand how the chapter's files were named; take a look at the following folder listing:\n\nAs I was removing image files from the manuscript and renaming subsequent files behind it, I was creating a situation where Second Copy thought it was doing the right thing by replacing the local copy of a file with the backed-up copy from the server. Here's what happened…\nSay for example I needed to remove image 1 (JMW01_01.jpg) from the manuscript; it was something that wasn't that important for the book and because of space constraints my editor has asked me to remove it. Now, once the file was been removed, I had to rename all of the following image files so there's a consistent naming scheme for everything. So, removing the first image file and renaming all of the other files (quite a pain I might say) would result in the following folder listing:\n\nNow, knowing that Second Copy has been diligently copying all of the files up to the server, it already has a copy of JMW01_01.jpg up on the server and, because of the renaming of the local files, has a different file date and time than the one on my local hard drive (remember, it used to be JMW01_02.jpg and it had a newer file date/time). The next time Second Copy runs, it's going to see that the server copy of the file has a newer date/time stamp than the one on my local hard drive. It's going to replace the local copy of the file (the former JMW01_02.jpg) with the newer file from the server (the former JMW01_01.jpg).\nWhen Second Copy gets done with its sync, the old JMW01_02.jpg (now called JMW01_01.jpg) will be replaced by the original JMW01_01.jpg from the server. Because JMW01_03.jpg has replaced JMW01_02.jpg (due to me renaming the files) the old JMW01_02.jpg is gone, deleted by Second Copy as it copied the old JMW01_01.jpg down from the server. Ouch! This created quite a mess.\nNot only was this process screwing up the files, it was also deleting files that I ultimately needed later. Very painful! It was a lot of work to completely rebuild the file structure every time this happened. I had to rename the files back to where they belonged and retrieve (hopefully) the right version of the archive. Since it might be some time before I noticed the problem I created, I would have to go back archive by archive until I found the one that contained the right version of the file I needed. I was frantically trying to finish the manuscript on schedule and keep my employer and my wife happy and now I'd created more work for myself. Crikey!\nNote: if the file extensions for the renamed files were different (a .tif file instead of a .jpg file for example) then this would not have created",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Writing a Book, Part 3 – Synchronizing Files",
  "date":"Sat May 15 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1273968000,
  "url":"/posts/2010/writing-a-book-part-3-synchronizing-files/",
  "content":"This article is the third in a series about some of the technical hurdles I faced while trying to write BlackBerry Development Fundamentals on my laptop (while on the road) and my desktop (when at home).  I'm trying to focus on the technical solutions I implemented so that others who begin writing a manuscript can benefit from my experience.  The first article in the series laid out an overview of the problems and the technical solutions I selected to solve them. The second article covered how I was able to ensure that I had a backup copy of every edit I'd made to the manuscript. This article covers how I synchronized the files between my two systems and, spoiler alert, caused some problems by doing so.\nLooking at the site's statistics, it's clear that not many of you are interested in this topic – I'm only getting a few hits on the articles. I'm going to wrap up this series this week (hopefully) then move on to some more interesting topics. In the mean time, here we go…\nAs I mentioned in one of the earlier articles of this series, while I was working on the book, I spent a fair amount of time on the road. It was ultimately a good thing since I was able to work long nights in the hotel room and make better progress on the manuscript without feeling guilty about ignoring my family. Because of this, I needed some way to work on the manuscript from my laptop and my desktop, but I didn't want to store the files up on a server somewhere – I wanted them physically on whichever system I was working on so that I could access them even if I didn't have network connectivity (which wasn't that often, but I didn't want to have to worry about it).\nWhile Windows has the ability to synchronize files with a server, it wouldn't work in my case because my laptop connected to my work domain and my desktop system didn't. I didn't want to have to deal with network domain issues. The solution I selected for this problem is a piece of software I've been using for years now called Second Copy. Second Copy is an award winning synchronization and backup tool that has supported me very well for a great many years. I use the solution to synchronize each system with a Windows server I have in my home office (The server is called Dinsdale; Monty Python fans might recognize the name) but it can also be used to write files to removable media.\nThe way I use this solution is to regularly synchronize the contents of my desktop system's 'My Documents' folder to a dedicated drive I have in Dinsdale for backups. Since my laptop was to be used primarily for work purposes, I only synchronized the contents of my laptop's 'FoBAD' folder (described in the second article in the series) with the corresponding folder on Dinsdale.\nAt first, I'd have the synchronization run every two hours, but before long I was getting regularly yelled at by Second Copy as it was trying to synchronize a file I currently had open. I later switched the process so my desktop would synchronize every morning at 6:00 AM (way before I was ever up working on the manuscript) and my laptop would synchronize on startup (as soon as I turned it on after returning from a trip) and every night at about 11 or midnight. With this in place, I had everything synchronizing nicely between the systems and it wasn't until much later that I realized I'd inadvertently created a problem by using this setup. The problem wasn't related to Second Copy, it had to do with some rearranging of files I was doing as I worked with the book's chapters. I'll explain more about this in the next installment of this series called Writing a Book, Part 4 – Fixing File Synchronization Errors. Stay tuned.\nJust in case you're interested in how Second Copy works, I'm going to show below how I setup the synchronization process in the program. When you install Second Copy, it launches on startup and puts a little application in the Windows system tray. It sits there patiently waiting for a scheduled job to begin then kicks off the process at the appropriate time and takes care of my file synchronization needs for me.\nTo setup a job, you have to create a profile; a profile in Second Copy defines actions taken upon a particular file folder on a computer system Second Copy has access to. The figure below shows the profiles I have defined on my desktop system.\n\nFigure 1\nWhen you create a new profile, Second Copy walks you through a wizard that allows you to select all of the options for the job. The first step in the wizard allows you to select Express or Custom setup for your profile. With Express setup, you're presented with a more simplified menu of options to use for your profile – this option is for inexperienced users who just want to get something done without looking at every possible option. For the profile I'm setting up here, I'm going to select the Custom option (as shown in the following figure) and click the 'Next' button.\n\nFigure 2\nThe wizard will next prompt you to select the source folder you will be copy",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Writing a Book, Part 2 – Batch Archiving",
  "date":"Wed May 05 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1273104000,
  "url":"/posts/2010/writing-a-book-part-2-batch-archiving/",
  "content":"As I mentioned in the first article in this series here, I needed a way to have a sort of version control system (VCS) without installing a version control system. I wanted something simple, something that would work regardless of whether I was connected to a network. What I decided to do was use the batch file processing capabilities of WinZip to create complete backups of the manuscript (including all documents and images). With this system in place, I could execute the batch process at the end of any editing session (or in the middle if I had a lot of changes) and have a complete backup of everything in case I needed to revert to some older version or dig up some old content I'd deleted and shouldn't have.\nBefore I begin, it's probably important to let you know that while I was working on the manuscript and before I had a contract with a publisher, my working title for the book was Fundamentals of BlackBerry Application Development. Throughout this article and others in the series, you'll probably notice that I named everything with the abbreviated version of the title: FoBAD. What's funny though is that I also registered a web domain for the book as a placeholder. All of the options I wanted were already taken, so I went ahead and registered bbdevfundamentals.com. I figured I'd grab that domain and later, when I had the final title, at least I'd have a domain to use if the one connected to the official title was taken. As I negotiated with the publisher for the title, imagine my surprise when the final name my publisher came up with was BlackBerry Development Fundamentals which, when abbreviated, matched the name of the domain I already secured for the book's site.\nThe requirements for the solution were:\n\nThe ability to execute the backup without selecting the files I wanted backed up every time\n2. The ability to automatically set the backup archive file name using the current date and time – this allowed me to have a unique file name for every backup which would automatically sort as needed in any file listing (Windows Explorer or My Computer).\n3. Take up as little file space as possible\n\nNow let's dig into how to setup the batch process I needed for my project. When you open any of the later versions of WinZip in Classic mode, you'll see a window similar to the one shown in Figure 1. You'll need to click on the 'Backup' tab to expose the options you need to create batch processes.\n\nFigure 1\nAs highlighted in the figure, select 'Create' to create a new backup job. WinZip will prompt you to provide a file name for your backup job. I suggest you put the job somewhere else than the folder you will be backing up. Use either you're my Documents folder or, as shown in the figure, a folder immediately above the folder you will be backing-up. In this case, I named the file FoBAD Backup.\n\nFigure 2\nWith the WinZip job created, it's time to start configuring the settings for the backup archive. WinZip uses a wizard metaphor for setting up jobs, so you'll be stepping through multiple screens as the job's settings are defined.\nIn the next part of the wizard, you're prompted to identify the files and folders that are included and excluded from the backup job.  In this case, I want to backup the contents of my FoBAD folder, but I don't want to have to store my backups somewhere else. So, I'm including the FoBAD folder but excluding my Backup folder (as shown in Figure 3. For the manuscript, I also had a folder where I stored all of the source code and research documentation I used as reference for the book. Since the content of that folder never got updated (only new items added to it) I didn't feel the need to include those files in my backup – it would take up too much hard drive space to be useful and I can always replace the content through an internet search. You can see the folders I'm excluding by looking for the 'Exc+Sub' in the Action column in the figure.\n\nFigure 3\nClick the 'Select items…' button to pick the items that are included and excluded from the backup job. The file selection dialog is shown in Figure 4. Place a check mark on the files or folders you want included.\n\nFigure 4\nIn the next step of the wizard, you can select which type of backup being performed. For my manuscript backup, I selected a normal backup which grabs all files regardless of the file's archive attribute setting. You can also use settings that allow for an incremental backup, differential backup or an update (refresh the contents of an existing backup archive).\n\nFigure 5\nNext the wizard prompts you to select some additional settings for the archive. I like to use the selection for relative folder information – that way I don't end up with the full folder path in my archive. With relative folders set, only the folder structure information below the starting folder is included with each file.\n\nFigure 6\nIn the next step is where the batch processing capabilities of WinZip become most useful. As you can see in Figure 7, you can spec",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Writing a Book, Part 1 – Getting Started",
  "date":"Sun May 02 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1272844800,
  "url":"/posts/2010/writing-a-book-part-1-getting-started/",
  "content":"After I completed BlackBerry Development Fundamentals, I thought I'd write some articles that outlined some of the process I followed to complete the manuscript. What follows is the first part of a series of articles that document the tools and procedures I used to help make the creation of the manuscript as painless as possible. In this installment, I'll lay out the issues I had to address and in subsequent articles describe each of the solutions I used to solve them.\nWriting a large word document is not that hard, but dealing with a complete manuscript (and associated image files) was rather challenging. As I worked, I quickly noticed that I was going to have a problem keeping my chapter files in good shape. I knew I'd be working on the manuscript from both my desktop PC when working at home and my laptop while on the road. The issue then was how do I keep all of the files accurately synchronized between the two systems and how do I maintain the integrity of the files as I worked on them.\nThe first thing I had to concern myself with was what tool I would use to craft the manuscript. Since I'd written a complete, 600 page product manual for ADT in Word, I knew that I could easily do it there. Having written my first book in Word then switched to Adobe FrameMaker for layout, I knew that I didn't want to do anything with the book in FrameMaker. I thought of using Open Office just for grins or perhaps Google Docs, but I know just how to put Word through its paces, so I knew I had to do all of my writing in Word.\nThe first thing I did then was created a folder for the manuscript and create separate Word documents for each chapter. Since I knew I'd have a different document for each chapter, I knew I wouldn't have to deal with any issues Word had with large files. I had a pretty good outline of what I wanted in the book (the end book ended up looking nothing like it) so I thought I'd be OK setting up each chapter and plugging through one at a time until I got it done.\nWhen I started the project, I forced myself to work on one chapter at a time, in sequence. I knew that if I jumped around, I'd never feel like I was making any real progress and I also knew I'd omit things. I started on chapter one then wrote each chapter in sequence until I completed it. That ended up being a very good decision and allowed me to demonstrate real progress to my publisher. Most published authors I've spoken with complained regularly about the schedules imposed on them by their publishers. I was already 6 chapters into the book when I received my contract from Pearson and ended up never getting a schedule from my editor. He got chapter by chapter from me in timely installments, so he knew he didn't have to worry.\nI made a couple of big mistakes with my manuscript as I started writing…\nFirst of all, I put each chapter file into the same folder. This seemed like a good idea until I started associating image files with each chapter. With each of the chapters in the same folder, all of the image files were there too. As I started placing images into the chapters as I worked through them, it got harder and harder to navigate through the folder to get to later chapter's image files. I quickly learned (well OK, not that quickly; I think I figured this out long past the halfway mark in the book) that the best thing to do was make a separate folder for each chapter and image files. That way, everything was together and it was very easy for me to zip up each chapter folder to submit a chapter to the editor for review. With the files all in one folder, I was able to right click on a folder in Windows Explorer and have WinZip package up all of the files in a zip file already named for the chapter (since the folder already referenced the chapter name). Once I got all that figured out, it became much easier to manage the manuscript files. If you're writing a novel, you can probably put all chapter files in the same folder; if writing a technical book or a book with a lot of illustrations; use a separate older for each chapter.\nThe second mistake I made was related to the Word Template my publisher wanted me to use. I took a look at it as after I began the project and felt that it was too ugly to work in day to day as I wrote the manuscript. They had a lot of special stuff you had to put in there (like a separate style for the first and last bullets in a list) and I thought it would be easier to write in a generic template then apply the publisher's template before submitting it for review by the editor. Wrong! As I got further and further into my manuscript, I started having to submit early ones for editing and found myself wasting a lot of time fixing a document (by applying the publisher's template and applying all of the special styles the publisher wanted me to use) when I should have been finishing up other chapters. When you write a book, get the publisher's template ASAP and start working with it right away – it will save you a lot of stre",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "WES Update",
  "date":"Tue Apr 27 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1272412800,
  "url":"/posts/2010/wes-update/",
  "content":"I'm attending Research In Motion's Wireless Enterprise Symposium (WES) this week. There haven't been a lot of big announcements, but some of merit.\nRIM announced two new phones on Monday – the BlackBerry Pearl refresh (the 9100) which is supposed to be slated for release by AT&amp;T but not really announced by the carrier. The BlackBerry Bold is making its way to CDMA carriers (Verizon Wireless in the US) with the new BlackBerry 9650.\nThey also announced BlackBerry Mobile Voice System (MVS) 5.0 which now adds support for Wi-Fi calling (VOIP) through MVS. I had an MVS account when I worked at Research In Motion and it was pretty cool. It's an interesting concept and great to have your desk phone ring on your BlackBerry.\nDuring the opening session, Research In Motion showed a video that highlighted the features and capabilities of BlackBerry Device Software 6.0. Research In Motion's been getting so much pressure in the market to update their UI to match that found on the iPhone and Android platforms and looks like they're set to deliver. I truly can't wait to get my hands on the new device software (It's not the OS although that's what many people call it – the BlackBerry OS is running at different versions numbers, it's the BlackBerry Device Software that the user interacts with) to see what's new. Apparently Research In Motion has done a complete UI refresh on all of the applications. The BlackBerry messages application is already VERY capable for my email use (I just can't stand the mail client on the iPhone) and I can only imagine this will be even better. It looked from the video Research In Motion showed that it's got a lot of cool new features.\nThere's a lot of speculation that Research In Motion's got plans for a hybrid device (one with a touch screen and a keyboard) and I'm not sure I believe it's true. It's likely they will do this – especially with BlackBerry Device Software 6.0's cool touch-based UI capabilities, but they're being pretty closed mouthed about it. Historically every 'leaked' BlackBerry device has turned out to be a hoax – I can't tell you how many times I'd hand a person the BlackBerry Bold 9000 and see them press on the screen. So many web sites said it'd be a touch screen device (even though I knew it wasn't slated to be) but there has never been a touch screen version and people still push on the screen with their fingers.\nI'm looking for some more big announcements coming at the conference, but I doubt there's any more pending. They did announce the dates for the BlackBerry Developer Conference – September 27 through 30. I'm hoping I can attend the conference again this year.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "The View Advisory Board",
  "date":"Thu Apr 22 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1271980800,
  "url":"/posts/2010/the-view-advisory-board/",
  "content":"The View updated its web site today and I'm now listed as a Technical Advisor for the publication. I'm excited and looking forward to writing mobility-related articles for the publication and getting other mobile domino geeks like me to publish articles. Let me know if you have a topic in mind.\nHere's a link to the advisor listing.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Accessing Domino Databases from Android and iPhone",
  "date":"Thu Apr 22 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1271980800,
  "url":"/posts/2010/accessing-domino-databases-from-android-and-iphone/",
  "content":"Last year I wrote a series of articles about how to build a BlackBerry application that talked to a Domino database. I intended it to be a series of three articles but it quickly grew to 4 and those articles have been heavily read and frequently commented on. I'm probably going to write a fifth article in that series that talks about some of the issues related to web services and JME and hopefully another article that shows how to talk to the same Domino web service from a BlackBerry Widget. I hope to get a chance to work on those articles in a while, but in the mean time I have some other things to write about.\nAt Lotusphere this year, I presented a session that basically covered everything that's in that original article series plus demonstrated writing a Windows Mobile application that talked to the same service (let me know if you'd like me to write an article about it – I'd thought of doing it, but wasn't sure if people cared). For this year's conference I wanted to spice things up a little bit and add Android and possibly iPhone examples of the same application to my session.\nThe thing about Android and iPhone is that unlike BlackBerry and Windows Mobile, the platforms do not have native support for consuming Web Services. So, in order to be able to work with Domino from Android or iPhone you have to find another way to do it. What I did for those sample applications was rewrite the code for the service into a Domino agent that returned JavaScript Object Notation (JSON – json.org) when called through a web URL. It didn't take me that long to do and it works very well, so I have what I need to work with the other mobile platforms. So, in the next few weeks, I'm going to publish an article that describes the JSON-based web service.\nI wasn't able to get the Android example done in time for Lotusphere (not without trying, I killed a lot of nights in Orlando during the conference furiously trying to get the app done – god thing I was recovering from pneumonia and didn't want to party anyway). A while after Lotusphere I finally got the application done, so I'm going to cover that application at the View conference in a few weeks. After the conference (perhaps before if I get time) I'm going to publish an article that illustrates how to build an Android application that talks to the JSON-based web service. Just so you believe that it works, here's a screen shot of the application.\n\nI'm most of the way through building the same application for the iPhone. It's been a nightmare building the application – Objective-C is so weird and complicated that I'm really struggling to finish the last part of the application. I'm planning to finish the application in time for the conference, I think I can do it, but like I said, I'm struggling. I'm probably not going to publish anything here about the iPhone application – I'm going to see if I can get an article about the application published in the View. Stay tuned on that one. Just to whet your appetite here's a screen shot of the application.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "What Were They Thinking 7",
  "date":"Thu Apr 15 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1271376000,
  "url":"/posts/2010/what-were-they-thinking-7/",
  "content":"Apparently March 18th was a big day for updates to applications in the BlackBerry App World. As the screen shot below shows, my device inbox was all of a sudden filled with notices of applications that needed to be upgraded.\n\nNice, I like that the system notifies me and I can tell quickly which applications need updates. When I opened the App World application, one of the things I quickly noticed was that App World didn't have the means to update all of the applications simultaneously. Instead, I was presented with a list like the one shown in the following screen shot.\n\nRather than give me an easy option to update all of the applications, I had to select each application individually and start the update for each manually. Granted the developers of the application didn't expect so many updates on the same day, but they probably should have.\nThis is one of the things I like about the Apple App Store, when there are a bunch of updates, you can click the 'Update all' button and all of the affected applications are updated.\nThis is a hard one – you don't want to code for every possible options for an application, but pick the ones that you think will happen most often (and cover other cases later). But the App World application has been updated several times and if the number of applications was expected to grow (as it has) then the developers should have made accommodation for the case where multiple applications have updates simultaneously.\nI'm currently working as a project manager for an application for a major retailer and one of the things that came up this week is related to this. The application is calling a web service to retrieve a list of items from a list the user has created. The Web Service the application is calling supports a calling method that returns all list items, but also supports an option that allows you to specify a starting point in the list and the number of rows returned to the calling function.  The developer of the iPhone application called the operation using the default option (all items) and during testing the customer found that the application quickly crashed. Of course, the developer only tested with short lists and the customer's QA department tested with huge lists. Both teams tested with unreasonable size lists and of course we had problems.\nIn this simple case, the developer, having seen that the back-end web service supported two calling methods, should have coded the application to accommodate very long lists in its original implementation. That way, the application would work with reasonable lists (10 to 20 items) but would also work when the list exceeded the original expectation. I know it's more work, but that's the way it should have been developed from the beginning. As it is, we're already a little late for release of the application and the developer is trying to submit a change order for the new work to implement the system in a way that should have been done this way all along.\nFor those of you who are Domino developers – look at how IBM managed the default behavior when rendering a view in the browser – the default behavior (and the expected behavior) is when the view is short, display all documents. When the list is long, render the view in pages and allow the users to page between chunks of documents until they find the one they want. Another smart thing they did was make the default number of view rows that are displayed a configuration value on the server, but also something that could be easily overridden in the ?OpenView URL.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "Multitasking iPhone",
  "date":"Fri Apr 09 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1270857600,
  "url":"/posts/2010/multitasking-iphone/",
  "content":"The big announcement this week came from Apple who finally announced background processing for the iPhone and iPad. Here's a snippet from an article in PC Magazine:\n\nWithin multitasking, Jobs also highlighted several capabilities, acknowledging that the company had been outpaced by other mobile operating systems with multitasking capabilities, just as other companies passed them in adding cut-and-paste capabilities. &quot;We weren't first to this party, but we're going to be the best,&quot; Jobs said.\nIf a user wants to shift to another app, he or she can double tap the &quot;home&quot; button. A &quot;dock&quot; with recent applications will appear, allowing the user to shift to another application. Apps that aren't being used become &quot;quiescent,&quot; and the OS saves their state and pulls resources from them. When the OS shifts back, those resources are re-allocated, and the user has a chance to resume where he or she left off, Jobs said.\n&quot;In multitasking, if you see a task manager, you blew it,&quot; Jobs said.\n\nFor me though, I'm still amazed at Apple's attitude toward its customers.\n'Outpaced by other mobile operating systems'? Apple wasn't 'outpaced' by other operating systems with their ability to cut &amp; copy text or run applications in the background - those are standard features that most every smartphone owner expects from their device and Apple decided for some bizarre reason not to include the features.  I just don't get it.  The only smartphone I can think of that didn't allow background apps was the Palm OS and I was surprised it lasted so long without the ability. Copy &amp; Paste? The only smartphone that I can think of that didn't allow that was the original Motorola Q. Those features are minimum requirements for any OS and for Apple to pretend that they were outsmarted by their competitors is a joke.\nRegarding Multitasking - how is Apple thinking double-clicking a button and bringing up a list of 'docked' applications to select from isn't a task manager? That button was designed to be clicked once to activate the device or take you back to the home screen - it's a pretty hefty push to activate it and people won't be good at double-clicking it. They've clearly tried for force fit this feature (when it should have been baked in from the very beginning). \nIt's not even true multitasking - notice how the article references that applications that are pushed to the background are suspended? They're not running, their used memory is stored and retrieved later when the application is reactivated. I'm sorry, but that's not multitasking. I understand how a mobile platform would want to have the ability to suspend background tasks when memory is low, but applications should be able to run in the background and only give up their memory when needed.\nImagine a user who's about to begging a time consuming task. He starts the task then switches to another application to do something productive while the original application is doing its stuff. In this scenario the user expects the application to continue with its processing, but according to the description of the 'feature' that's not what will happen.\nThe iPhone and the iPad are amazing devices, but I'm still continually stunned by Apple's analysis of the market and what it thinks its users will accept as reasonable. Of course, I've been having some serious arguments lately with some friends of mine and one of them contends that Apple is catering to people who don't care about these features and that they'll just take whatever Apple gives them. I have to admit I don't get it.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "My New Apple iPad and Some Book Reader Problems",
  "date":"Thu Apr 08 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1270771200,
  "url":"/posts/2010/my-new-apple-ipad-and-some-book-reader-problems/",
  "content":"OK, so I got an iPad. I ordered one as soon as I could pre-order and had to wait an extra couple of days to get my hands on the device because I inadvertently had it shipped to my old address and was out of town on the 3rd. It finally arrived on Monday and I've been amazed with it ever since.\nIt's a truly amazing device and feels great in your hands. I've started downloading a bunch of news applications (I really want to be able to keep up with my local and world news on it – no more paper newspapers) and some fun drawing tools for the kids. What amazes me the most is the weather applications that are available for it. Considering the weather we've had here in North Carolina tonight (tornado watches and warnings) my wife and I have been sitting with it watching the radar maps and local weather report videos.\nIt truly is going to be a game changing device – I'm convinced that it's going to completely change the way people interact with computers. I found TweetDeck for it and I'm waiting for the FaceBook application to become available for it. I've found that the web browsing experience is really great – the browsing I've done and the surveys and form data entry I've done has been very comfortable.\nI have been experiencing some pretty poor Wi-Fi connectivity issues. It was comforting to hear that others are having the same problem and that Apple has responded. My Wi-Fi access point is in one end of my house and I can't access the network on my iPad from the other side of the house. Even 25 or 30 feet away I'm really not getting the throughput that I should be getting. I'm going to wait semi-patiently to see what Apple does about the problem. This is the first Apple computing product I've purchased since my old Apple //e (with 1 MB of memory mind you) and I still believe they make amazing products (although I remain unimpressed with Steve Job's (er, I mean Apple's) attitude about iPhone applications). My employer has provided me with an iPhone and recently a MacBook (so I can do some iPhone development) and I'm having a lot of fun playing with the products. I'm still a BlackBerry user day to day, but the iPhone is great for applications. When the new OS becomes available and I can finally run background applications I'm sure I'll begin using my iPhone more frequently. Unfortunately Research In Motion really doesn't seem to be trying to stay in the sexiness game and it saddens me.\nI am having a problem with the iPad Book Reader application. I've purchased some books (I even found a free Isaac Azimov book from Project Gutenberg) and I spent a recent road trip reading on the iPad. I've found it to be a very nice experience. The Book Reader application though has some formatting problems that I thought I'd point out.\nWhen the book reader displays an italicized word next to a regular word, it scrunches up the space to the left of the italicized word so it looks like it's right next to the preceding word (no space between the words) as shown in the following figure.\n\nFigure 1\nFor those readers of my What Were They Thinking series, the problem I'm having isn't related to the font size I have set on the device – rest assured that I'm running it at the default font settings for the device.\nAdditionally, when the reader uses small caps to render a person's title, I'm having the same problem – the words are all scrunched up as shown below:\n\nFigure 2\nAnother thing I noticed is that when the Reader displays an Initial Caps for the first letter in a paragraph that it inserts some extra space between that line and the line that follows. It's not like it needs the extra space, it just adds it unnecessarily.\n\nFigure 3\nI'm going to keep watching to see if others are experiencing the same problem and whether Apple takes the time to fix it soon.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "BlackBerry User Defection",
  "date":"Thu Apr 08 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1270771200,
  "url":"/posts/2010/blackberry-user-defection/",
  "content":"Did you see the survey results published recently about BlackBerry users saying they'd get an iPhone if they had to get a new phone today?  Check out Why BlackBerry Users Will Defect when you get a chance. Very telling and I hope the folks at Research In Motion are listening.\nAnother interesting note appeared online this week. The makers of the SkyFire browser announced that they were discontinuing development for the BlackBerry platform. You can find the announcement here. RIM just hasn't kept up with the market when it comes to platform capabilities. People want the iPhone and Android UI experience and they're done waiting for RIM to provide it. Look at RIM just releasing the development tools for BlackBerry Device Software 5.0 - the OS has been out for months now and RIM's finally getting around to releasing the development tools? Sad. Granted they were available in Beta for a long time, but who wants to build products or Enterprise applications with beta software?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Addendum to What Were They Thinking 6",
  "date":"Thu Mar 25 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1269561600,
  "url":"/posts/2010/addendum-to-what-were-they-thinking-6/",
  "content":"A reader was kind enough to comment on my article: What Were They Thinking #6 and pointed out that the issue I was writing about was caused by my personal settings on the BlackBerry. If you look at the figure, you'll see that I'm clearly going blind (just kidding, just having trouble reading things) and have the font on my BlackBerry device cranked up high. The reader was right, the problem I was complaining about was my fault, but I contend that it still never should have happened. Here's my take on this:\nFirst of all, since I'm looking at a listing of free apps, there's no need to list 'Free' for every item in the list. They're all free, there's no need to take up the screen space (and processing time to render) content that is not needed. Do you agree that highlighting the 'freeness' of a free application that's clearly already fee is a waste?\nSecond, although I agree that the issue I'm reporting is related to my personal font settings, it is the responsibility of the developer to detect the size of the fonts being used and adjust rendering on the screen accordingly. The developer of the application should have detected the font size (they already did since we can see they used my font settings to render the screen) and make sure everything fits correctly using that font. There's no reason he or she couldn't have seen that the text as written was not going to fit into the allocated space (using the settings I've defined) and wrap the text on the screen so me, the user, would be able to read the entire application name. This is something I had to do in my Official's Record Keeper application in all of the reports. For any text I wanted to write to the report canvas, I had to check it's width and wrap it manually in the code. It's a pain in the you know what, but it's something that should have been addressed by the developer and I stand by my complaint.\nLook at all of the extra, unused space created by the height of the application logo. They clearly had the room to extend the row to accommodate the wrapped application title. I'd rather have the extra space under the icon than under the text block - especially since I can't read the entire application title as it is.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "What Were They Thinking 6",
  "date":"Tue Mar 16 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1268784000,
  "url":"/posts/2010/what-were-they-thinking-6/",
  "content":"For this installment of my What Were They Thinking series I'm going to pick on Research In Motion. Considering that they invented the whole smartphone market, they're usually pretty good about designing BlackBerry applications with forethought and an attention to detail. After all, they created the platform and they're responsible for maintaining consistency across all applications. Right?\nI was browsing through the list of free applications in the BlackBerry App World application yesterday and was struck with how hard it was to read the application names in the list of free applications. See the figure below for an example of what I saw:\n\nWhen building a mobile application, you have to pay special attention to first of all how much data is delivered across the wireless network and how much work the application has to do to process and render the data. This is wireless application 101 stuff.\nWhen you look at the application list, you'll notice that they've designed the application so you can see the application's icon (useful for branding purposes) but only a portion of the application's title. I don't know about you, but I can't tell what the application names are for these applications.\nOn top of that, take a look at how much screen space is taken up by the word 'Free' for each application. We already know it's a list of free applications – if we didn't remember that when we looked at the screen, we could have easily been reminded by looking at the 'Top Free' in the title bar. There's no need to show the word 'Free' for each application – they're all free. It's extra screen space that could have been used to allow more of the application name to display.\nSince I can't read the full application name, I have to open each application to learn what the app name is – bad use of my time. There's also absolutely no reason why the application title can't wrap around to the next line.  Who cares if it takes up an extra line on the display? If you look closely at the screenshot, you'll see that there's wasted space anyway underneath the application vendor name. They didn't try to scale the application icon to the available space used by the application title and vendor – what they should have done was kept the icon the same size and adjust the font sizes to allow three lines of text for the application title and vendor.\nWhich is more important, making it easy for the user of the application to be able to read the information on the screen or keeping all rows the same height? I'm hoping you will agree with me that the user is more important here. I don't mind if I can't read the whole vendor name, but I do mind that I can't tell what the application's name is.\nWhat were they thinking?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "Getting Ready for the View Domino Conference",
  "date":"Sun Mar 14 2010 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1268611200,
  "url":"/posts/2010/getting-ready-for-the-view-domino-conference/",
  "content":"I've gotten involved with the View Domino Admin/Developer Conference again this year. The 2010 conference will be held in Boston (as usual) and runs from May 12th through the 14th.\n\nFor this year's conference, I'm doing my Domino Rich Client application session I did last year at the conference and also this year at Lotusphere. Of course I have to change it up a bit between each session. In last year's View conference, I showed how to build a Domino Web Service (the same web service I've written about here) then how to build a BlackBerry MDS Runtime application that talked to the service, a BlackBerry Java application and a Windows Mobile application.\nMDS Runtime has since been end of lifed by RIM (December 31, 2009), so for Lotusphere I pulled MDS Runtime from the presentation and did BlackBerry, Windows Mobile and tried to get Android done in time for the conference, but wasn't able to show a completed application. I had a horrible time with some of my demo's, everything crashed but I was still able to show everything (because every good presenter has a back-up copy of everything ready to show).\nFor this year's View conference, I've finished the Android version of the application (it's pretty cool and I learned an awful lot about Android in the process) so I'll be showing that along with the BlackBerry application. I was thinking of also showing the Windows Mobile application again, but I'm just not sure people really care about it. With the forthcoming Windows Mobile 7 breaking every previous version of the application, the Jury's out as to whether I should still show it. Let me know what you think. Even though the slide decks are due today, I'm planning on spending the rest of the time between now and the conference building the same application for the iPhone. I'm going to first do the development using XCode and Objective-C but hopefully I'll have time to build a browser-based application as well using DashCode. We'll see what happens and how much time I have to throw at this.\nAs I promised after Lotusphere, I will be publishing an article about how to build the Android application here (with source code).\nI'm also doing a session entitled &quot;Current Trends in Mobile Application Development&quot; where I'll be talking about the current trends in mobile application development.\nI've also taken a position as a Technical Advisor to The View publication. I'm going to be focusing on mobility related topics and hopefully penning some articles for the publication. Stay tuned for more information.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "The iPhone In the Enterprise",
  "date":"Tue Mar 09 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1268179200,
  "url":"/posts/2010/the-iphone-in-the-enterprise/",
  "content":"A colleague asked me a while back to provide my comments on InfoWorld's Enterprise iPhone Deep Dive Report. I found it to be an interesting read and I was convinced when I finished that you should never allow a bigot to write an article if you're going to pretend that you're impartial.\nI could be wrong on this, and as usual my comments below do not reflect the official position of AT&amp;T, but here's my take on the report:\nI'm not sure the iPhone is capable of satisfying the enterprise and the different articles in the report highlight many of the issues, but not really the root cause behind them.  Apple historically has never really 'understood' the enterprise and until now it hasn't really been an issue. Now that these organizations have all of these remote devices accessing corporate data, it's even more important that Apple understand the enterprise.  Buried deep within the report was the following statement:\n\n“Apple designed the iPhone as a consumer device, so it's heavy on convenience and light on security. If you want protection, you have to accept some pain”\n\nNo enterprise is going to be interested in hearing that unless they're willing to forgo security in order to have the cool device (which is currently the case with many enterprises).\nIf you think about the platform, it was designed under the premise that users would not run any application other than the applications provided by Apple or a select few of very trusted partners. The web browser, being a desktop browser in a small package rather than an actual mobile browser, was deemed to be sufficient for all user needs. The tradeoff they got by making this assumption was that they could build the platform allowing all applications to run with root level access within the Unix security model. They wouldn't need a security model since they weren't planning on allowing anything but their applications to run. All applications run with the same level of access and each and every application can do anything it wants to anything else on the device. No sandboxing, no varying levels of access (Apple applications running with the most access, other applications running with less), nothing. Everything runs as root. No system administrator on any unix system in the world would allow that for any end user computing device, but that's what Apple did with the iPhone.\nAfter Apple decided that end-users did want to have access to applications, Apple quickly 'patched' the environment to allow third-party applications. They took a system designed with no security and added a security model (of sorts) on top of it. Now, third party applications could be created and Apple reserved access to some API's for itself – most likely over security or performance concerns. What I believe, unless Apple has done a complete rewrite, is that the iPhone platform doesn't have the foundation enterprises need to feel that the device is secure in their environments.\nI believe that Apple's prohibition of background applications is another offshoot of this design. Since they didn't build the necessary security restrictions in the original platform, they have to worry about applications running in the background, gaining access to all sorts of information and data the enterprise would otherwise not want accessed. By not allowing background applications, they can avoid any security concerns over inter-process communication.\nApple's getting there with regards to support for ActiveSync policies. More and more policies will be added over time. What's clear from the article is that if you're on ActiveSync, many of the enterprise security features you need are there and I believe more and more will continue to appear with each release of the platform.  If you're not on ActiveSync, then your choices for enterprise management are:\n\nBuy a third party product\nUse the free tool Apple offers, the iPhone Configuration Utility\n\nThe problem with the iPhone Configuration Utility is that while you have the ability to configure all sorts of settings, there's absolutely no way to ensure that these settings are deployed and correctly maintained on the affected mobile devices. None. The user has to act to implement the security feature you have created for them. Enterprises security departments will not accept that as an option. The report later says:\n\n“But a big IT issue remains: you can't easily manage iPhones through a central console wirelessly, even though you can do some management (profiles and remote wipe) via email, the web and/or Exchange 2007. IT Pros rightfully complain that Apple essentially forces them to use a local PC as a management workstation and physically connect user's iPhones to it”\n\nThe conclusion correctly reached in the report is that ActiveSync good, anything else bad. Since the majority of enterprises are running Exchange, most organizations should be OK.  \nThere's still the issue where any iPhone prior to the 3GS would report to ActiveSync that it was capable of encrypting or w",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Motorola Backflip",
  "date":"Sun Mar 07 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1268006400,
  "url":"/posts/2010/motorola-backflip/",
  "content":"Just got my Motorola Backflip. So far I like it. It's a consumer device, but has support for corporate email and policies. I'll be playing with this over the next couple of weeks and I'll write a review. I'm really excited about the device - all signs point to Android exceeding the iPhone in the Enterprise Market (which is where I work).\nHere's a couple of things I learned as I played with the device for a few minutes:\nMotoBlur is pretty cool. In a matter of minutes I had my account created and setup Twitter, Facebook and personal email. Limiting that you can only define one Twitter account (I have two). Supposedly MotoBlur provides better Exchange ActiveSync support than what is available in Android 2.1.\nThe device has a touchpad on the back of the screen. When you're holding it open in your hands with the keyboard exposed, you can navigate the screens by swiping on the back of the screen. The front is a touch screen, but the back gives you a different sort of navigation. Different. Interesting. Time will tell how useful/fun this is or how much it enhances the usability.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Back & Forth",
  "date":"Sun Mar 07 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1268006400,
  "url":"/posts/2010/back-forth/",
  "content":"One of my college Physics professors said something one day that stuck with me. Someone in the class said 'back and forth' and he stopped them and said that it was physically impossible to go back and forth. You can go forth then come back to the initial state, but you can't go back then forth. It was a very literal interpretation, but it stuck with me all these (many) years.\nI made the mistake of using that on my boss a while back and he's not let me forget it yet. Of course, he reminded me, you can go back then forth if you're talking numerically - start at zero then go back to -3 then forth to 6. I agreed, but I'm sure he'll find other examples and ply me with them.\nHe mentioned a good one and I promised to write about it. He said - think about all of those products that are new and improved. Think about it, they can't be both new AND improved. That have to be one or the other.\nThanks Jim!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Where Android beats the iPhone",
  "date":"Thu Mar 04 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1267747200,
  "url":"/posts/2010/where-android-beats-the-iphone/",
  "content":"When you get a chance, take a look at a recent article from InfoWorld: Where Android beats the iPhone. The author writes about his experience with the Google Nexus One and the Android platform from a developer's standpoint. What's interesting is his very accurate and honest comparison of Android development against Apple iPhone development - especially targeted at the Enterprise.\nI have an article I haven't published that talks about why the iPhone platform is like it is and I hope to publish it soon (just need to give it another read and clean it up a bit) but what's clear is that decisions that Apple has made are getting ready to bite them in the ass. The InfoWorld article is just one of many that compares the iPhone with how easy it is to do very useful things on other devices. It's not that the iPhone can't do them - it's that Apple just won't let you do them. Here you have an amazing, sexy, capable device and so many of the smart and useful things that consumer and enterprise developers want or need to do on their iPhones are just not allowed.\nI've been spending a lot of time lately working with companies and vendors who are building consumer and enterprise applications for the iPhone and other platforms. It's amazing to hear how many times these efforts have been thwarted merely by Apple's refusal to allow common behavior that is possible (I don't like to say allowed but that's basically the issue here) on every other smartphone platform on the market today. Developers are starting to revolt (look at what the developer of the Facebook application for the iPhone did a few months ago: here) and the market is going to turn away from the iPhone platform. This is going to happen only because of Apple's policies and in spite of the fact that it's a very cool, sexy and capable device.\nThe breadth of things you can do with the iPhone are being limited by the vendor, not by any limitations of the device. That's definitely going to hurt Apple in the market.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Apple Does Not Care About the Network",
  "date":"Mon Mar 01 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1267488000,
  "url":"/posts/2010/apple-does-not-care-about-the-network/",
  "content":"I was at a meeting before Christmas and someone from Apple was presenting on the application development capabilities of the iPhone platform. What was interesting from the session was that Apple was touting all of these developer-related features that really didn't differ from the capabilities of the other major mobile platforms. For everything that he mentioned (with one exception) I could point to the exact same capability being available on the BlackBerry and other platforms. I'm not sure what was going on here - I guess he assumed he wasn't talking to a Developer audience (he really wasn't) and could get away with it.\nThe one exception? Background applications. Yep, most other platforms do it (heck, the Palm platform finally does) but the iPhone doesn't. I finally figured out why Apple doesn't allow background applications on the iPhone - I hope I get time to write about it soon. No, it's not for the reasons they say. I was really, really surprised that the guy could explain away the prohibition against background applications with a straight face, but he did. I guess he earned his pay that day.\nAnyway, back to the purpose for this post. Apple really doesn't care about the mobile network. As you'll see in a post I'm writing for posting (hopefully) tomorrow, it's in Apple's best interest to have the most compelling application platform (they do). What they want is everyone developing for the iPhone and being upset because the same applications (I'm talking about the web here) just don't work well on other platforms (they don't). They want to be the leaders in the mobile application space (they are) and really don't care how they do it.\nSo, during this session with Apple, they explained that there's this cool new application you can download from the App Store that allows you to stream video from one iPhone to another. WHAT??? They're promoting device to device streaming video? Imagine being at your kid's school play and streaming the show to your spouse who couldn't make it? Wow, that's cool - but think about the network! The iPhone is already killing AT&amp;T's network and now they're deploying an application that allows even more saturation of the network? Yep, that's it - they really don't care about the network. Someone in the audience raised his hand and asked about the impact this would have on an already saturated network and the guy from Apple rolled his eyes, placed his hands behind his back and refused to answer. He just stood there for a little while until someone asked another question. Is that amazing or what?\nImplementing any features that makes better (read 'reduced') use of the network would reduce performance for the user and therefore impact the user's overall experience with the platform. Users would get snappier applications, increased battery life and would ultimately be able to do more with their devices, but that's not 'cool' or market leading. Carriers would get less complaints about the network and more users would be able to get more done at the same time, but it only affects one Wireless Carrier in the US so how bad could that be?\nThe best thing that could happen to AT&amp;T and iPhone users would be for other US Wireless Carriers to get the iPhone as well. When all Wireless Carriers and users are being affected by this disregard for the network I bet we'd see the market force some changes on Apple to make the iPhone (and soon the iPad) play nice with others.\nDisclaimer: Recognizing that I work for AT&amp;T, the content in this article is my personal opinion only and does not reflect the opinion or public voice of AT&amp;T.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "There's Something Wrong with the Site",
  "date":"Thu Feb 11 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1265932800,
  "url":"/posts/2010/something-wrong-with-the-site/",
  "content":"There's something up with the site, it's not rendering correctly.The home page seems OK, but when you drill into any of the categories it's broken. Ouch!\nI tried to install a FeedBurner module yesterday and now everything's hokey. I'll see what I can do to fix this.\nUpdate: I've been poking and prodding at this and I just can't figure it out. It's not only this site that's broken, but all of my Joomla sites being hosted on Fatcow. I asked Fatcow for help and what I got in response was this:\n\nHello John,\nIn Joomla Configuration settings, we have disabled and enabled 'Search Engine Friendly URLs', 'Use Apache mod_rewrite' ,'Add suffix to URLs' and set .htaccess file, still the website links loads with broken themes. It appears that you had installed any new joomla modules or plugins. Please disable those plugins and check the website functionality from your end.\n\nWhich is effectively telling me nothing. Yes, I have added extensions, but when I opened the ticket I told them I disabled everything and it didn't change anything.\nThe admin functions are working great and the home page renders correctly. It's just when you open any other of the site that isn't working correctly. The content appears, but none of the templating is applied. I'll continue to troubleshoot this, but I'm moving this week, so my time is limited (sorry). I'll also keep begging FatCow to help me figure this out. They mentioned they changed directory permissions all of a sudden SugarCRM is working but my Joomla and vBulletin sites aren't.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "More FatCow Woes",
  "date":"Wed Feb 10 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1265846400,
  "url":"/posts/2010/more-fatcow-woes/",
  "content":"Well, after receiving yet another ridiculous response from FatCow I spoke with a tech who escalated me and passed me on to Jason who agreed my problems were ridiculous and promised to escalate and follow the progress of my call through the support process.\nOf course, a few hours later I received the following response:\n\nDear Sir/Madam,\nThank you for contacting support.\nI regret, if you want a version of Sugar CRM installed other than that available through Install Central, you will need to carry out the installation yourself. We can not assist with this process, and are very limited in the help we can provide with regard to any problems that result from such an installation outside of Install Central, or troubleshooting which may be required. You would need to contact the manufacturer or supplier of the software for help with their product. I am sorry for any inconvenience that this may cause.\nThank You,\nJim M.\nTechnical Support\n\nNot only did he (see, I can tell it's a he) make any effort to try to determine whether I'm a man or a woman (I am a Man), he also decided that they don't support the application I'm trying to install. This is after I've been working with several people at FatCow for weeks on the problem.\nHonestly, I love (or used to love) FatCow, but their support organization is abysmal.  Normally I would recommend them, but they're proving to me (repeatedly) that they have no idea how to provide web-based support. When you call, they're awesome, but when you work with them through the web ticketing system - they're horrendous.  Repeatedly horrendous.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Lotusphere 2010 AD114 Presentation",
  "date":"Mon Feb 08 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1265673600,
  "url":"/posts/2010/lotusphere-2010-ad114-presentation/",
  "content":"Note: removed obsolete attachments November 11, 2022\nA lot of people have asked me to post the slide deck from my Lotusphere 2010 Beyond the Browser: Building Rich Client Applications for Domino (AD114) session. I wasn't sure whether I was allowed to post it, but I received the following confirmation from the track manager:\n&quot;Attendees can download whole tracks from Lotusphere online so please direct them there if for some reason they are not aware.  For non-attendees, you can post the slides on your site.&quot;\nSo, that being said, the presentation is attached to the end of this article\nThe session was a lot of fun although the Demo Gods rained trouble on me. I was prepared for that and had finished demos ready, so nobody left without seeing how it worked. That didn't stop people from complaining about it in their session evaluations though. Oh well, sometimes you just can't win. I'm making some progress on the Android sample application I showed a part of in the session. I should have that done in a few weeks (need to finish my move to North Carolina first). Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "SugarCRM and FatCow",
  "date":"Sun Feb 07 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1265587200,
  "url":"/posts/2010/sugarcrm-and-fatcow/",
  "content":"I've been trying for some time now to get the open source SugarCRM Customer Relationship Management system to work on a couple of my web sites being hosted by FatCow. It just doesn't work. After trying FatCow's automated install several times (which worked, but Sugar wouldn't run after the installation completed) and many manual installations of SugarCRM 5.5 (the latest version) I decided to give FatCow support a call. FatCow's usually awesome and sine they're giving me so much for very little money, I try not to call them too often.\nI spoke with a tech who told me what I was asking for was more complicated than he could handle (I like honesty) he immediately escalated me and I spoke with a guy (Jordan I think was his name) who understood my problem and got to work. He immediately tried their automated install - it failed with the exact same errors I was getting (validation, I love it). Then he downloaded the latest community version files (free) from the Internet and did the installation himself - it failed again (even more validation that my error was reproducible). He opened a ticket and promised to escalate it to Engineering.\nI waited a couple of days and received several emails from FatCow as they tried to work through my problem. Of course, some of the messages I got were related to the technicians just not reading the case history (I hate that and FatCow does it all the time - phone support is AWESOME, but dealing with online support is HORRIBLE for that reason alone). They finally told me that were able to get it installed and operational. Unfortunately they installed an old version (4.4, I'm trying to use 5.5), they installed it in a location different than where I asked to have it installed and they REFUSE (yep, absolutely and repeatedly refuse) to tell me anything except that they have it installed. I've asked what they did to get it to work - won't tell me. I've told them that I need 5.5 to work, not 4.4 and the only response I get is 'SugarCRM works on our systems' - nothing else. Arghhhhhh!  These guys are usually so good but in this case, they're absolutely refusing to actually help me with my problem.\nNow, I know FatCow doesn't 'support' SugarCRM, but they'll install it for me and it's just PHP, MYSQL and some other stuff - it should work just fine, right? Every single other product I've tried to install on their systems work just great (Joomla!, Drupal, vBulletin, phpBB and more).\nI've been working with the folks on the SugarCRM forums for help and finally got a chance tonight to look at one response where another customer is having difficulty with SugarCRM on FatCow (https://sugarcrm.com/forums/showthread.php?t=56281). So now I know it's not just me having troubles. I'm stil lnot getting anywhere with FatCow support - for the 10th time now I've said 'please, why won't you answer my questions' - I'm going to call tomorrow and see if I can get a manager on the phone or speak with my original tech since they are clearly demonstrating that they're not interested in helping me.\nTheir service is so awesome for a very reasonable amount of money that I hate to complain. The issue though is that I'd gladly pay more money per year (I already have two accounts just so I can give them more money - I'm serious) to get the help I need but they just don't seem to care.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "What Were They Thinking 5",
  "date":"Wed Feb 03 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1265241600,
  "url":"/posts/2010/what-were-they-thinking-5/",
  "content":"As part of my family's move to Charlotte, it was time to start looking for a new bank. We selected Bank Of America and proceeded to setup our new accounts. It occurred to me to take a look to see if the bank had an iPhone application and I was pleased to find that they did. I downloaded the application from the iTunes and proceeded to launch it. When the application starts, it presents you with the screen shown in the following figure.\n\nFigure 1\nYou can then define your account login information (including the same additional security measures Bank of America uses on their desktop browser application) and access all of your accounts and transactions. It's pretty cool and I like it. I'm not going to show you this with my own accounts (yes, I blanked out my login name in the figure below), but I'll describe it. What you see after you login is a list of your accounts. When you select an account, you're provided with a list of transactions and other information.\n\nFigure 2\nThe only complaint I have about the application is that it's very sluggish – after you login and start navigating through the account information, the screen response is very slow. Whoever wrote the application apparently didn't know how to optimize the menu items and so on to provide the best user experience.\nWhere the What Were They Thinking stuff begins is when you look at the BlackBerry version of the application.\nI didn't expect that there'd be a BlackBerry version of the app. It wasn't until I'd used the iPhone version for a while that I thought to look in the BlackBerry AppWorld for the app. Surprise of surprises – Bank of America also offers a BlackBerry application. So many times, vendors decide that all people care about is the iPhone application and skip other platforms. In this case, they are trying to accommodate multiple platforms. The problem is that they didn't implement the same features in the BlackBerry version of the application.\nWhen you open the BlackBerry version of the app, you see the screen shown below.\n\nFigure 3\nIt looks like the same features of the iPhone application. When you open the 'Locations Near Me' option, the application uses the GPS information available on the device to determine the location of the nearest bank locations – very nice.\nWhen you click on 'Mobile Banking Sign In' you'd think it will prompt you for your credentials and allow you to view account information (just like the iPhone app). Nope, that's not how it works here. When you select this option, you're presented with the following screen.\n\nFigure 4\nWhat???? The Browser? What were they thinking? The iPhone application shows an interactive list of accounts then allows you to browse the account transactions inside of a native iPhone application. The BlackBerry application launches the browser and gives you the exact same functionality you'd get if you fired up the browser and typed in bankofamerica.com in the address bar. The browser???\nEventually you get to the login prompt and you just have to deal with the mobile browser version of the site.\n\nFigure 5\nWhat's the point? It's essentially useless except for the branch finder. I just don't know what they were thinking. The bank spent the time and money to build a fully functional iPhone app but relegated BlackBerry users to a simple application that merely launches a particular URL in the BlackBerry browser.\nDevelopers: Please don't do this. The functionality the application needs to call on the back end to get the account information and account activity clearly exists (the iPhone application is using it) and the BlackBerry platform supports the exact same application capabilities that the iPhone does (the same API's are generally available across both platforms) so why the difference? I bet it was harder to do for the BlackBerry and it will take them some time to deliver parity. I'm OK with that – UI's are just easier to build on the newer platforms (iPhone, Android).  But the BlackBerry can call any service on the back end and process the data – just like the iPhone app. If it's too hard to build the long list of account transactions like used in the iPhone application, just have the server return the activity as HTML and render it in a BrowserField in the BlackBerry version. You'd still get the same data and you can make it look like the iPhone application although on non-touchscreen BlackBerry devices it won't be as easy to navigate. You could always intercept the click within the browser field and open up the selected account activity record natively.\nAnyway, my personal opinion is that hybrid applications for the BlackBerry should be avoided at all times. If you need to launch the  browser to provide your application with specific functionality then you're not really trying to build a BlackBerry app – all you're building is a shell program that uses the browser for its heavy lifting and I'm really not interested in using that kind of application.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "I Love it When Bob Cringely Gets Mad",
  "date":"Thu Jan 28 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1264723200,
  "url":"/posts/2010/i-love-it-when-bob-cringely-gets-mad/",
  "content":"Robert X Cringely used to publish on pbs.org and now publishes his own blog at cringely.com. He has done a bunch of cool things related to the PC industry over the years – including being the author of Accidental Empires: How the Boys of Silicon Valley Make Their Millions, Battle Foreign Competition, and Still Can't Get a Date which I really loved.\nAnyway, he writes about US Security every once in a while and recently published the following regarding how hard it was for US Officials to determine whether this Christmas Day Bomber was a terrorist:\n\n“Instead of just complaining, let's take a look at the issue from another angle. Contrast these three situations: 1) you are sitting in a hotel bar in Mongolia and want to use your Visa card to buy a round of drinks for your friends, and; 2) your Mom is at the check-out counter at a Sears store when the clerk asks her if she wants to apply for a Sears credit card and save 10 percent on her order, and 3) a possible terrorist with a dubious travel record and suspected al-Qaeda connections is standing in line at a European airport waiting to board a flight to the U.S. that leaves in an hour. What happens in each of these cases?\nIn Mongolia the bartender takes your card and authorizes it in seconds across a 12,000-mile round-trip. At the Sears store the transaction is not only authorized in less than a minute, but a new account is created and both your Mom's identity and her creditworthiness are established and calculated on the spot, along with her discount. Meanwhile the airline, airport, local security, European police, Interpol, Transportation Security Administration, Department of Homeland Security, Customs Service, FBI, CIA, and NSA can't between them figure out in an hour whether this guy standing in line in Holland should be allowed on the plane or not.\nHow is it that we can run our credit card operations so well and our national security so poorly?”\n\nHe's right and has every right to be mad. Read the full article: https://cringely.com/2010/01/predict-me-im-from-the-government.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Android Development Trials & Woes",
  "date":"Mon Jan 25 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1264464000,
  "url":"/posts/2010/android-development-trialswoes/",
  "content":"As I mentioned last week, I'd been trying to build an Android application for my rich client session at Lotusphere 2010 (AD114). I got off to a very late start, but with the right resources I thought I could throw something together to show in my session.\nI took the XML-based web service I created for the BlackBerry Java and Windows Mobile examples (they both provide native support for XML-based web services) and created a new one that used Representative State Transfer (REST) to process the request and return some JSON with the results. The agent is working great, I'll write about it in a little while.\nI created a Android Java project in Eclipse and started coding through my sample application, reading a couple of books as I went. I got the main application working, got the search box and the button that called the service working and was finally able to connect to the local Domino server to request the data (read about that here). As I tried to figure out the Android ListView widget, my application crashed and I just couldn't get any further. I poked and prodded in Eclipse and the simulator and just couldn't get anywhere.  Whenever I load the application, I get the following screen:\n\nIt's something in the startup of the application, but it's not telling me anything about the source of the problem. On the flight home, I read more about the LogCat view in Eclipse that would allow me to see what Android is saying when the application crashes. It turns out that there's an uncaught exception being generated when the application starts. Here's the relevant log lines:\n\nAt least I know what's happening now – all I need to do now is figure out the source of the problem. I'm disturbed that I'm not getting more information in the UI about the problem. On the BlackBerry platform, you'd get an error message identifying that there is an uncaught exception and listing the exception that should be caught. If I had that information, I think I could find this problem pretty quickly.\nOK, so I dug into the code and found the problem. I was using EditText and TextView widgets to create some of the UI. EditText widgets to accept user input and TextView widgets to display some text on the screen. When playing around with some things, I'd inadvertently cast the TextView as an EditText object (that happens some time when you're copying and modifying code). As soon as I changed the cast to TextView, the application is running again. Woohoo! \nThe line containing the information I needed is here:\n\nNext step is to figure out how to use an Android ListView widget to display the array of names that is returned by the Domino server. Stay tuned…\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "AT&T Public Policy Blog",
  "date":"Fri Jan 22 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1264204800,
  "url":"/posts/2010/att-public-policy-blog/",
  "content":"OK, so I work for AT&amp;T now and that focuses me more regularly on AT&amp;T-related topics, but I'm trying to write about them only when they apply to a wider mobility or telecommunications topic. I was poking around today and discovered AT&amp;T's Public Policy Blog.\nWhile probably not very interesting to people all around the world, but I did find some interesting articles about AT&amp;T's response to the FCC regarding Network Neutrality. This topic has fascinated me for a while and the Jury's out (as far as I'm concerned) whether the results of this whole argument is going to be a good thing or a bad thing for me (us). I know I want to be able to do whatever I want with the network pipe my provider provides me and at the same time I understand the network provider's concerns about how their network is being used. Ultimately it should be the consumer's who's rights are protected (I know, I'm biased) but the result if we have our way will be that the network providers will ultimately charge us more for what we get - just to protect their investments in network upgrades and management hardware so we can have what we want.\nAnyway, the site has several exhibits AT&amp;T submitted along with its response to the FCC that highlight some of the background details and outline what many think will happen depending on how this argument goes. I'm printing out hundreds of pages from the articles right now to read on an airplane in the next couple of weeks. i'll probably have more to say once I've read through all of them.  Stay tuned.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Android Application Demo for Lotusphere",
  "date":"Tue Jan 19 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1263945600,
  "url":"/posts/2010/android-application-demo-for-lotusphere/",
  "content":"I had to abandon my plans for demonstrating an Android application talking to a Domino Web Service for my session this morning. I'm disappointed. I spent a lot of time learning it and working through the kinks. I got it to a point where I was able to access the Domino service and was getting data back when all of the sudden the application just stopped working on the emulator. I'm going to keep at it and write something I can put up here for everyone to look at, but I just won't be demonstrating it here at Lotusphere 2010. I got too sick before the holidays (still not recovered yet) and just didn't have the time to do this right.\nWhat I did to support this application platform was create a new service to use for iPhone and Android. Windows Mobile and the BlackBerry can use the XML-Based Web Service that Domino supports natively, and that's what I'm going to show in the session. But for other platforms (the iPhone and Android don't support XML-Based Web Services natively) I created a service that uses REST (Representative State Transfer) to process the data. It works really well and can also be used in a Widget using XMLHTTPRequest (which I'll show here as well some day).\nSo, expect to see the new RESTful Domino agent documented here soon followed by the Android application, a BlackBerry Widget and, now that I have a MacBook to play with for about 90 days, an iPhone version as well. This is going to be fun. I'll be moving right in the middle of all of this, so I don't know when I'll get it all done.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Battery Bit",
  "date":"Mon Jan 18 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1263859200,
  "url":"/posts/2010/battery-bit/",
  "content":"I'm going to try to coin a new phrase this afternoon in my Browser Development tricks session at Lotusphere 2010. I wanted to write about it here first, just in case it takes off and I get credit for the idea. The term is &quot;Battery Bit&quot; or, as I decided to try out early this morning, 'Battery Bit Time.' I'll explain what it means in a little bit (no pun intended).\nI've been doing a lot of analysis of the wireless development space and have noticed a couple of trends. The biggest one is that developers have begun (mostly because of the iPhone) to completely disregard the network and the limited capabilities of mobile devices when they build their applications – especially their mobile web applications. We're dealing with small devices with limited processing capacity, limited memory and limited battery life, and developers are regularly building apps that no longer take that into consideration. They're treating these smartphones like they're desktop computers and that's causing problems for everyone.\nAT&amp;T is getting hammered by its customers and by the press for its network problems, but honestly (as an AT&amp;T employee it's very important for me to point out here that the statements made in this post are my personal opinion and in no way reflect or represent the thoughts or opinions of my employer) it's the users &amp; applications and their complete disregard for the network that are causing the problem.  The network is fine – and recent independent tests have concluded that it's faster and better than its competitors; it's how the network is being used that's creating all of the problems. I hope to get some time in the next couple of weeks to write more about this because I think I have some interesting insights into this – but we'll see if I can carve out the time to do that writing…\nOK, now back to Battery Bit Time. As Mike Lazaridis (the founder of RIM) says, there's no way to get around Physics. Every bit of data that is delivered to and processed by a mobile device has an impact on the device battery life, the wireless network and the application user. Let's dig into this.\nEvery single bit (or byte, depending on how you look at this) of data transmitted to and/or from a mobile device affects the battery life for the device. If you send less data, you'll likely get better battery life out of your device. It's simple Physics (or as my father would say “it's Basic Physics”), every amount of work the device is asked to perform drains the battery. There's just no way around it. So, what happened to the days where mobile developers took that into account with their applications? It's gone. The iPhone is basically a small desktop device – even its browser refuses to identify itself as a mobile browser. It's regularly downloading full, desktop versions of web sites across a wireless network that shouldn't be processing so much data. Developers should always (and yes, I do mean always) send as little data as needed across the wireless network to provide the needed functionality for the application. No more than needed. There's no need for Flash, images, cool transitions or other glitz – just send the data the user needs and nothing else. Mobile web sites should be text-based, nothing more. If you do this Developers, you'll allow your users, through the simple application of Physics, to achieve better (longer) battery life for their mobile devices. Since Apple has decided we're not worthy of being able to swap out batteries (which all other mobile devices do) when we run out of power this becomes even more important for iPhone users.\nAs with every bit of data transmitted to/from a mobile device, every bit processed by the mobile device application (whether it be a browser or custom application) has an effect on the user. Every bit of work done by the processor further drains the battery. There's no way around the Physics of this. It's why as much processing as possible should be done by the back-end server, minimizing the work done by the client-side processor. When building mobile web sites or rich client applications, as cool as the technologies are that allow you to crunch data locally and create a very cool and compelling visual experience for your applications – it's not needed on a mobile device and does nothing but drain the battery and decrease the responsiveness of the application for the user. See my article about the BlackBerry Developer Conference application for more on this topic.\nTaking this even further, every bit of data transmitted to/from a mobile device and every bit processed by the mobile device application increases the amount of time it takes to display the data on the screen for the user to access/act upon. Mobile devices and mobile applications provide immediacy – give me access to the things I need access to when I need access to them. Right? By building these complicated applications – web applications with all this funky, dynamic rich content or native applications wi",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Android Emulator Access to LocalHost",
  "date":"Mon Jan 18 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1263859200,
  "url":"/posts/2010/android-emulator-access-to-localhost/",
  "content":"In preparation for my presentation at Lotusphere tomorrow, I've been beating my head against a problem and finally found a very simple solution. I thought I'd share. I'm trying to add an Android example to my rich client session and because I've been sick, I didn't get to work on this until this week. Nothing like last minute coding, eh?\nAnyway, I have the Domino server running on my laptop and I've been trying to connect to it from the Android Emulator for about a day now. You can't use localhost, because localhost on a mobile device (whether it be an actual device or an emulator) points to the local device. The emulator therefore doesn't know about the local laptop through that reference (which is what you'd do to do any local testing laptop app to laptop app).\nThe original web site where I found this information is no longer up, so here's the details:\nFor an Android application running on the Android Emulator, to allow the application to access network resources running on the system running the emulator use the IP address 10.0.2.2.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "What is 3G",
  "date":"Sun Jan 17 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1263772800,
  "url":"/posts/2010/what-is-3g/",
  "content":"There's this big fight going on here in the US between AT&amp;T and Verizon (the two largest wireless carriers) about who's network is better than the other. Verizon has taken the approach that their 3G network is bigger than AT&amp;T's network and AT&amp;T has taken the approach of arguing that their network is faster than Verizon's network and allows simultaneous voice and data which Verizon's network does not.  It's important to note that I work for AT&amp;T, so have to be careful what I say here.\nThe ads are funny and I'm not sure who's winning but there's an interesting point to be made here….\nWhat normal, every day mobile user has any idea what a 3G network is? I know because I work for AT&amp;T and used to work for Research In Motion, but what about the every day user for which these ads are targeted? They're being inundated with all of this talk about 2G and 3G networks (not to mention the 2.5G networks [whatever those are]) – and it all just doesn't matter since the normal consumer has truly no idea which G network they need for their smartphone. They probably think that 3G is better than 2G and 4G will be better than 3G, but they probably just don't know why. They're only using about 10 to 20% of the features of their smartphone, so faster speeds probably don't mean that much to them.\nThe big issue here, and I intend on writing about this when I get a chance, is that no matter what network you're on, it's likely that it will be saturated with all this traffic being generated by all of these smartphones running all of these applications that have no respect for the network (more on that later too). As soon as the carriers upgrade to the new 4G (faster than 3G) networks, more and more smartphones and more and more network unaware applications will fill those networks too. As the processing speeds and capabilities increase on these smartphones, all they'll do is use even more bandwidth and there's likely no way the carriers can keep up (just my humble, personal opinion).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "My Book is on sale at Lotusphere 2010",
  "date":"Sun Jan 17 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1263772800,
  "url":"/posts/2010/my-book-is-on-sale-at-lotusphere-2010/",
  "content":"As I've written before, I'm at Lotusphere 2010 this week presenting two sessions on mobile development. When I was accepted as a speaker, IBM asked whether I had published a book and offered me a chance to have the book available in the onsite book store at Lotusphere. There was no guarantee that it would make it into the store, but I was excited to see this morning when the Solutions Showcase opened (yep, I ran down as soon as it opened) that there is a stack of BlackBerry Development Fundamentals for sale (at 20% off) at the show. I'm so excited. We'll see how well they sell.  If you're here, please help me out by purchasing a copy. I'll even sign copies if you track me down.\nMy publisher also provided me with 5 free copies of the book to distribute at the conference. I'll give them away at the end of my sessions (I'm presenting three times). I'll most likely give them to the people who ask the best BlackBerry questions at the end of the session.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development"
  
  ]
  },

  {
  "title": "Android Coming to AT&T",
  "date":"Sun Jan 10 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1263168000,
  "url":"/posts/2010/android-coming-to-att/",
  "content":"Although I'm a BlackBerry guy at heart, I've always been interested in Android. As I see it (from reading analyst reports and the press) Android is going to make a very big splash in the Enterprise mobility market in 2010 and 2011. Considering Android (like BlackBerry) was built from the ground up with Enterprise Mobility in mind (unlike the iPhone) it's likely that BlackBErry and Android will become the dominant players in the enterprise by 2012 (which has been predicted by the analyst community). Being an employee of AT&amp;T I was excited to finally see the official announcement about the Android-based phones I will have access to. See the press release.\nI've been studying up on Android development in preparation for Lotusphere. I'm going to be demonstrating how to build a BlackBerry, Windows Mobile and hopefully Android rich client application (not the browser) accessing a Domino application in my session (AD114). I have a new laptop to configure and get ready for the conference, but I hope I have the time to add the Android example to my demos.\nI can't wait to get one or more Android devices in my hot little hands so I can finally play with the platform at length. I'll be sure to write about it as I know more.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "Google Nexus One",
  "date":"Tue Jan 05 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1262736000,
  "url":"/posts/2010/google-nexus-one/",
  "content":"Back when the US FCC was auctioning off the 700 MHz spectrum to mobile carriers and Google announced its intention to bid I was sure that Google was about to for a dramatic change in the wireless industry. With their building the Android platform, buying up of all that dark fiber, building data centers along river banks (for cooling and power generation) in the Dakotas and building those shipping container data centers they were supposed to put at the Internet's major access points - I was sure they were going to set themselves up to compete with the existing carriers and force a change in the way the US wireless carriers did business.\nWhat I imagined was Google setting themselves up as a wireless provider using the 700 MHz spectrum I was sure they were going to buy then offering essentially free devices in return for the ability to run local ads across a dedicated portion of the device screen. Anyone would be able to walk into a Best Buy or WalMart, plunk down $50 or $100 and have essentially a device with free wireless network access. When they pulled out of the auction I wasn't quite sure what they were all about and I'm still not sure.\nWhen all of that press generated a few weeks ago about the proposed Nexus One device - a mobile device Google would sell direct - I was certain it was all bunk. That they just wouldn't try to go direct like that. Well, Google made the announcement. With this new device, people will be able to plunk down the full price for the device and get an unlocked device they can use on any compatible network (just like I believe you can in Europe and other parts of the world). Once I walked into a carrier sales center with a device I already owned and only had to pay a monthly fee for service (no contract) I promised myself that I'd never do anything but purchase the device at full price and use any carrier I wanted. Now Google is making it so it's very easy for me to do this. No begging your carrier to allow you to unlock it - just buy an unlocked phone directly from the manufacturer and do whatever you want with it.\nIt's going to be very interesting to see what impact this is going to have on the US Wireless Carrier market.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile"
  
  ]
  },

  {
  "title": "AT&T wants FCC blessing to shut down PSTN",
  "date":"Mon Jan 04 2010 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1262649600,
  "url":"/posts/2010/att-fcc-blessing-shut-down-pstn/",
  "content":"My wife and I sold our house on Christmas Eve and purchased a new one on New Year's Eve. Wild times this holiday season I can tell ya. On top of that I contracted H1N1 and Pneumonia - I can't tell you how much fun that was.\nOne of the things we've been talking about is whether we're going to order landline(s) for the new house. My wife and I both have mobile phones of course and our kids don't get phone calls but by the time they do, they'll probably have their own mobile numbers. I've always argued with my wife about having wired phones in the house (I'm OK with cordless phones, but wanted at least one wired phone in case of a power outage). I won that argument after a huge winter storm knocked out power for a few days and she was able to call people because I had the necessary wired phones available to her. It's always fun to be right....\nAnyway, since I work for AT&amp;T now and get pretty good pricing on phone lines, I decided that even though the trend was to go completely wireless rather than installing landlines that I'd get one anyway (actually three - home, home office and one for McNelly SoftWorks) just because it would be very convenient. The house we purchased is 11 years old, so it still hase RJ-11 jacks everywhere. Not sure that would be the case in any new house I purchase/build in the next couple of years. So, for this house we're installing landlines expecting that not to be the case for the next one.\nI was looking through the press the other day and found the following article: AT&amp;T wants the FCC's blessing to shut down PSTN which indicates that AT&amp;T (the number one provider of Plain Old Telephone Service (POTS) in the United States) has begun lobbying the FCC to allow it to shut down the landline telephone service. It makes sense, everyone nowadays is using their mobile phone as their primary phone numbers; any kid coming out of college will have one number and will never install a landline in any apartment or house. It won't be very long before landlines become more and more expensive because less and less people are using them. What does it mean for businesses?\nEven though consumers aren't using landline phones anymore - how does a business have a phone number if AT&amp;T is shutting down the analog Public Switched Telephone Network (PSTN)? Of course everything switches to the broadband network. We'll all be using VOIP I expect and companies and old guys like me will be getting their POTS line through my high-speed broadband connection running into the house. I expect service will be the same, but it will require more hardware I expect and an ever bigger load on the broadband connection.\nI expect it would relieve a huge burden if AT&amp;T didn't have to maintain both PSTN and broadband networks. Getting rid of the analog network would allow them to dedicate much more money toward providing better broadband and wireless service. I wonder how long it will take them to get approval and to get the network shut down. 10 years? 20 years? 50 years?\nWhat I'm interesting in seeing is when the wireless carriers finally get their act together and allow VOIP for mobile calls as well - how cool would it be if I could get my personal number and my business number ringing on the same mobile device? It's a smartphone, right? Should be smart enough to do that. \nTime will tell...\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "My Problem with Foobar",
  "date":"Sun Dec 27 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1261958400,
  "url":"/posts/2009/my-problem-with-foobar/",
  "content":"I read a lot of computer books and application development books – you'd have to expect that considering what I do for a living. Recently I've been catching up on some of my Joomla! books and of course reading the BlackBerry development books that followed mine and there's something that always bothers me in these types of books and I thought I'd rant about it a little bit…\nIn most development books, the authors always use 'foo', 'bar' and/or 'foobar' as sample function names in their sample code. What I can never tell is whether the person using those terms understands what they're doing or whether someone did it once and everyone else just followed.\nLet me give you some background:\nA very long time ago (who knows how far back – Wikipedia says it was in 1944) some army grunt used the term FUBAR to describe something that was 'mucked up beyond all recognition' or 'mucked up beyond all repair' (depending on which version of the story you hear) substituting an 'F' for the 'M' in mucked of course. The term was apparently very widely used in the US army (or so my father told me from his experiences in the Korean War).\nWhat I can't figure out is how the term got mangled into something that's used so often in computer books. The term is clearly not something that you'd expect to people to use in a book, so I guess that's how it became foobar instead of FUBAR. Probably mostly because it would be too easy to mispronounce 'fu' as perhaps fuh instead of foo – so that's why 'they' made it 'foo'? Anyway, why is this being used? I'm not offended by the term, but it is a crude and impolite word to use in a regular, every day book.\nIf you read the Wikipedia reference for FUBAR and foobar, the writers there have clearly tried to pretend that the words are not related (confusingly the FUBAR page says they're not related: 'Not to be confused with foobar' but the foobar page mentions that foobar may actually be related to FUBAR). How could they not be referring to the same word? Some developer geek heard about the expression and started using it in his sample code and before we know it, it's being used everywhere. Why can't the sample function names be something like function1 &amp; function2 or somefunction &amp; anotherfunction instead of foo and `bar? It just doesn't make sense to me.\nThe reason this all came to mind I guess was that many people use words like this without really knowing what they're saying. I purchased much of the furniture in my house from a family run furniture company in Amish country (although they were not an Amish family – just craftsmen living in Amish country). I was speaking to the owner's wife about a communication issue related to a delivery to my house when she said “I'm so sorry about the SNAFU.” I was completely taken by surprise by her comment – she was after all a quiet, polite lady in her late 50's or early 60's. I laughed for a minute then asked her if she knew what SNAFU meant. When she said that she didn't, I told her that that expression was another Army term standing for 'Situation Normal, All Mucked Up' (or course again substituting an 'F' for the 'M' in mucked). She was shocked and stunned and quickly promised “I'll never use that term again!”\nAnyway, feel free to disagree with me, but I'm certain the initial use of foobar in computer sample code was a sort of trick played by some geek a long time ago and we're stuck with it in every new computer book that comes out. I wish people would drop it – again, it's not that I'm offended by it, I just think it's stupid to have that expression (although a slightly modified one) used in professionally produced books. I wish the editors would all get together and ban that term from all code examples in computer books going forward. I promise that you won't find the expression in BlackBerry Development Fundamentals and in any other book I write!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Internet Scam 20091216",
  "date":"Fri Dec 18 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1261180800,
  "url":"/posts/2009/internet-scam-20091216/",
  "content":"I got an email the other day that announced that McNelly SoftWorks had won an award: “The Small Business Commerce Association (SBCA) is pleased to announce that McNelly Softworks LLC has been selected for the 2009 Best of Business Award.” I thought that was interesting considering that McNelly SoftWorks really doesn't do much anymore. I started the company many (many, many) years ago and it offers two software products but really only sells one (and sells that one poorly at that).\nI knew it was a scam as soon as I read further: “Best of Business Award in the Computer software tape and disks: blank, rigid, and floppy category.” Um, McNelly isn't in the software tape and disks market – so I knew whoever awarded this award really didn't know ANYTHING about my company.\nHere's the text of the message:\n\nFigure 1\nI started looking around to try to see if this message had anything in it that would help me understand the nature of the scam, but it didn't look funky at all. I went to their web site and noticed that it was just a front for what looked like a fake organization. As soon as I saw the announcement that the company was funded by the Federal Government (in very poor English) I knew I had a confirmed scam. I searched around the Internet and found the following link: https://scam.com/showthread.php?p=806477 explaining the source of the scam.\nApparently they give out these 'awards' and charge you an exorbitant fee for a plaque you can display in your place of business. I wonder how many unsuspecting people get duped by these guys or how many pay the fee for the plaque and don't know any better.\nAnyway, too funny – I'm so tired of people calling me or sending me unsolicited email messages (in direct violation of US Federal Law mind you) without actually knowing anything about me or my business. I'm sure they assume I'm some small to medium sized business rather than one guy working out of his basement, but it's ridiculous that people fall for these kind of things. I guess if you're a growing business that things like this would look good on your wall, but you have to know it's a shady deal if you've never heard of the organization and their web site is so lame. The good news is that you can go to their site and register for the 2010 awards – maybe you'll win one too.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Lotusphere Schedule",
  "date":"Thu Dec 17 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1261094400,
  "url":"/posts/2009/lotusphere-schedule/",
  "content":"I received the Lotusphere schedule last week. I was very excited to see that our BP212 session was selected to be a repeat session - that's never happened to me before. Way cool.\n\nHere's the schedule:\n\nBP212: Tuesday from 3:30 PM to 4:30 PM\nAD114: Wednesday from 10:00 AM to 11:00 AM\nBP212 (repeat): Wednesday from 1:30 PM to 2:30 PM\n\nBe sure to track me down and say hello!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "What Were They Thinking 4",
  "date":"Wed Dec 16 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1261008000,
  "url":"/posts/2009/what-were-they-thinking-4/",
  "content":"My company recently asked us to install and use an application on our BlackBerry devices and as soon as I saw the application icon, I knew I had another topic for my 'What were they thinking' series.  Please take a look at the following BlackBerry screen shot:\n\nIf you take a look at the last icon in the first row, you should be able to easily tell that it just doesn't match the look of all of the other icons on the device's home screen. When working with the Apple iPhone or Windows Mobile devices, there isn't really any adherence to any theme when it comes to application icons. On the BlackBerry platform on the other hand, the icons on the home screen are designed specifically to look similar to all of the other icons in the theme - mostly because it's a theme and that's how themes work.\nWhen building application icons for BlackBerry devices, it's a good idea to make sure your application icon matches the 'theme' of the default theme for the particular device. I know this means more work for the developer, but if you don't do this, you end up with screens like the one shown above.\nThe reason this is a problem for me is that, because of the way the developer designed the application icon, every time I looked at the device, it looked to me like the bright orange icon shown in the figure was the currently highlighted icon. Every time I looked at it, I immediately assumed that was the one highlighted and tried to move it off of that icon to the application I'd intended to open. Every time (and I promise you it happened many, many times), the 'Profiles' application or my 'Messages' application was actually the selected icon and I felt like an idiot. You shouldn't use icons that contrast so starkly with the other icons on the device - the selected icon should be unique, but at the same time should blend in with the rest of the theme.\nIn this case, I'm sure it wasn't that the developer wasn't thinking. What really happened I bet was that the icon was the last thing added to the application right before it was released and the developer just threw something together so he or she could finish the project and move on to the next one. Considering the orange color and globe icon are synonymous with my employer, it's easy to see how that was what was selected in this case. Also, this application was created using one of the MEAP tools (I won't say which one) and therefore had to run across multiple platforms, so it's likely that's why a theme appropriate icon was not selected for this application. If it were me, I'd have made sure that the icon was less...standoutish (like a sore thumb).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "Internet Scam 20091207",
  "date":"Wed Dec 16 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1261008000,
  "url":"/posts/2009/internet-scam-20091207/",
  "content":"I received another really interesting email the other day and I thought I'd write about it in my continuing series on Internet Scams. I got an email supposedly from American Express as shown in the following figure:\n\nFigure 1\nThe thing about it though was I knew that American Express didn't have this email address. My ISP flagged it as Spam, always a useful aid and there were a lot of other things about the message that confirmed that it was just another scam.\nIn my Outlook inbox I used Qurb (now called 'CA Anti-Spam Plus') which makes sure that no messages make it into my inbox unless I have them in my contact list, I've written to that address or manually approved the address previously. That makes it easy to spot Spam since all suspect messages are siphoned off into a special folder that I can peruse later to free up messages from new, approved senders. Thunderbird on the other hand doesn't have (that I know of) a whitelisting Spam filter, so I have to drill through my Spam manually. Fortunately it does support the identification of Junk senders and uses Bayesian Probability to identify Spam based upon the messages I've marked as Spam previously. Here's an article from Wired Magazine where I first heard of this technology.\nAnyway, as I read through the email I saw a lot of things that assured me that this was spam. For the screen shot I turned on message headers - which provide me with a whole bunch of additional information about the source of the message. I blurred some if the information in the screen shot to help protect my ISP's servers.\nLet's go through the list:\n\nMessage Subject: Not likely that American Express is going to send me a message about an 'American Express Online Form.' There couldn't possibly be anything like that I'd need to address.\nAmerican Express would always address me by name, not using 'Dear American Express Customer.'\nMessage Body: It just doesn't make sense.\nLogo: There's no American Express logo in the email anywhere. The scammer sent an HTML format email message rather than plain text, so you'd think since it's already HTML that a logo file would be displayed (further luring me into believing that the message actually came from American Express).\nTo Address: The message was sent to 'info@mdecorporation.com' which isn't where it was delivered (it was delivered to info@mcnellysoftworks.com). That's a sure sign that it's Spam!\nReceived Address: From looking at the message headers, it's clear that the message thinks it was received from an account at The University of Texas at El Paso (utep.edu). Ya, I'm pretty sure American Express is not going to send me a message from a University computer system/account.\nReturn-Path: The headers show that the return address is set to an email account in Russia. I'm pretty sure American Express isn't going to be sending me email messages from Russia.\nX-Mailer: The headers show that the message was sent by Microsoft Outlook Express 6.00.2900.2180. I'm pretty sure American Express is not going to be sending me email messages from Outlook Express.\n\nThat's all I have for this one. I'll keep posting these things as they come up – it's just fascinating (for me anyway) to see these messages dissected.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Problems with the BlackBerry App World Application",
  "date":"Tue Dec 15 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1260921600,
  "url":"/posts/2009/problems-with-the-blackberry-app-world-application/",
  "content":"I've been having a problem with the BlackBerry App World application lately. I go looking for it and it's just not there. I keep re-installing it and it keeps going away. I started looking around on the forums and found a few posts on it.I'm going to follow the posts for a while to see if I can learning anything of interest.\nI just reinstalled it and when I start the application, I get the following error:\n\nI just uninstalled and it's rebooting. We'll see if a clean install fixes this problem. Perhaps I was running a version for the 8900 that got moved over when I upgraded to the 9700 so maybe there was some weird incompatibility with the version I was running. We'll see what happens.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Alt-rbdb",
  "date":"Mon Dec 14 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1260835200,
  "url":"/posts/2009/alt-rbdb/",
  "content":"At the BlackBerry Developer Conference I picked up a tip that I thought would be very useful and I'd planned on writing about it but ran into a hitch...\nI've always made great use of the alt-rbvs key combination you can use to view the source code for a web page in the browser. At the conference someone (I don't remember who) said you could use alt-rbdb to browse the JavaScript DOM for the web page open in the browser. As I tested it out and I found that it didn't work on my device. After asking a former colleague at RIM, I found out that that particular feature only works on RIM's internal Engineering devices.\nToo bad, I was sure people would get great use out of this feature. Perhaps in the future RIM will implement it in all devices. Please let me know if this works on any of your devices.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "What Were They Thinking 3",
  "date":"Sat Dec 12 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1260662400,
  "url":"/posts/2009/what-were-they-thinking-3/",
  "content":"This example of 'What Were They Thinking' is for a Java application, not a web application - but I thought it would be an interesting addition to the series. It refers to something that absolutely drives me crazy in BlackBerry Java applications and I've seen the same kind of thing on other mobile platforms as well. Here we go...\nAs i've mentioned before, I'm getting older and with my advanced age comes reduced eyesight. If you see in the sample screen shot below, my BlackBerry client is configured to use pretty large fonts:\n\nThis approach makes it easy for me to read the screen without my reading glasses (which I've not yet gotten around to keeping with me always). I know this takes up more screen space, but it's something I just have to do.\nNow, last week I was working in RIM's Chalk application (Chalk is a recent purchase and allows organizations to easily push rich content to devices). When I opened the application's main screen, here's what I saw:\n\nThe developer (or developers) who built this application, selected a font and size to be used for the application without paying any attention to how I had my particular device configured. For me, it's completely unusable without my glasses.\nWhy do developers disregard the user when designing their applications? The BlackBerry device provides me with the means to configure the screen using any font and font size I want, but I have to deal with applications that completely ignore that. I know they've done this so they can give their application cool effects (like the graphical background you see in the figure) but that just doesn't take the needs of the actual user into account. I know any 20's user can see this easly, but it just doesn't work for us that are in our 40's.\nMobile developers - when building rich client applications on mobile devices, query the system to determine the font and font size selected by the device user and use that to craft any and all of your application screens. It's unreasonable to do otherwise. Trust that the device user knows better than you do how he or she wants text displayed on the device's small screen.\nI'll try to scare up a sample application that does this (on the BlackBerry of course) so you can see how it works.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "What Were They Thinking 2",
  "date":"Wed Dec 09 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1260403200,
  "url":"/posts/2009/what-were-they-thinking-2/",
  "content":"At first I thought I might have difficulty finding enough examples to make this an interesting series but that's turning out to not be the case. Just on a whim, I navigated over to linkedin.com to see how their site looked on the BlackBerry Browser. I expected that they'd detect that I'm running a BlackBerry and give me a mobile version of their site, but I was wrong - take a look at the following screen shot:\n\nThe LinkedIn developers broke the first rule of Mobile Web Development: Always (and yes, I do mean always) Detect the Browser!\nWhat were they thinking? I cover this in the book, but it's important to highlight something here.  Because of the iPhone and other smartphones, developers are building their sites disregarding the information available to them about the target device. The iPhone and the Storm for example have pretty large screens, so 'normal' sites render on them OK, so developers have gotten lazy and just assume everyone's a desktop browser and tosses out the page. Unfortunately, even though the modern smartphone can render pages designed for the desktop (because of their supports for desktop browser standards and the larger screen than earlier smartphones) it doesn't always make sense to do that. Big web pages on small screens just don't look right (see the figure) and it's disrespectful of mobile users to send a whole bunch of gunk to the browser (graphics and a bunch of menu items).\nMobile web sites must be designed with the mobile user in mind and crafted so the user can get as quickly as possible to the data that matters to them. In this case, LinkedIn doesn't seem to be sensing that I'm accessing their site from a BlackBerry and gave me their standard page. Developers must always detect the user-agent and send a text-only, designed for small screen page to mobile devices.\nOn the BlackBerry and other mobile platforms, the user has the choice of changing the browser's personality to IE or Firefox.Let the user make this configuration change then get the whole page when they have the browser impersonating a desktop browser. Then, when people like me who let the BlackBerry announce itself as a BlackBerry, send a mobile-friendly version to all mobile devices.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "What were they thinking?",
  "date":"Tue Dec 08 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1260316800,
  "url":"/posts/2009/what-were-they-thinking-1/",
  "content":"For our Lotusphere presentation in January, Rob Wunderlich and I started talking about how to approach our topic about mobile web development. One of the things that came up was an agreement that a lot of developers, while they know all about web development, didn't think of the ramifications of their decisions as they mobilized their sites. Even though the mobile browser supports most of the web development standards, it doesn't mean you should make use of them. Also, even though you know how to build a site for a desktop browser, doesn't mean you should do the same thing for the mobile user.\nWe decided then that the underlying theme for our session was going to be 'What were they thinking' and in preparation for that I have started collecting examples of bad (bad, very bad) things that mobile developers do that makes life hard for mobile users. As I collect these things, I'll start posting them to the site and see where I can take this.\nThe first example for this series is is shown below. I am at a hotel attending some sales training (yep, I'm a sales guy now) provided by my employer and tried to connect to the hotel's wireless network to do some work. My BlackBerry Storm 9700 was smart enough to recognize that I was on a hotspot network, so immediately launched the hotspot browser so I could login to the access point before going on to do my work. When I looked at the page, I noticed something that I thought I'd share with you as the first rule in the 'what were they thinking' series.\nTake a look at the following image:\n\nThe site gave me an easy way to select my language that didn't consume too much screen real estate (always a good thing). Imagine how much harder it would have been to use if there was a big list of languages or a drop-down list containing the list of supported languages?\nWhere the developer went wrong was in the way he (or she) used the radio button. Whenever you present a radio button to a mobile user and there's only one item in the list, you make them do extra work to select that tiny little button before clicking next. The smart developer will detect how many items there are in the list and either remove the choice all together or, if you're going to put a single item in a radio button list, pre-select the only available option. Don't make the user make the selection if there's no possible other option for them to use. It just doesn't make sense to make the user do that extra work when it's not necessary. \nI'm a little older and I'm starting to have trouble reading mobile device screens without my glasses, so when I was first presented with this page I immediately clicked the next button and didn't think about the radio button.Of course the page errored out and I had to go back and pay close attention to what I was doing - but this wasn't a good use of my time.\nIf you're building a site like this, please think about the impact of these types of things on your user. There's no reason to force a selection when there's really nothing to select.  Make sense?  Implementing this in dynamic environments like PHP or Domino is really, really simple - just a simple if statement with two different HTML outputs depending on the number of options in the list.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Mobile Development",
  
    "What Were They Thinking"
  
  ]
  },

  {
  "title": "Speaking at Lotusphere 2010",
  "date":"Tue Dec 01 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1259712000,
  "url":"/posts/2009/speaking-at-lotusphere-2010/",
  "content":"I'm excited to announce that I've been selected to present two sessions at Lotusphere 2010.\n\nRob Wunderlich and I are presenting a session entitled: 'Delivering IBM Lotus Domino to Mobile Devices: Top 10 Mobile Browser Dev Tricks.' The topic stems from some sessions Rob's done at previous Lotuspheres and some sessions I've done at the View Domino Administrator/Developer Conference. It's designed to highlight the trips and tricks of building Domino browser based application for mobile phones and smartphones. There's so many things web developers need to worry about when working with mobile devices – we're going to try to lay it all out for people who attend the session.\nRob and I have been working on the outline for the session and it's really beginning to come together. I've known Rob for a long time and he and I both have interesting perspectives to bring to the session. We're having some interesting discussions about some common misconceptions and things that need to be taken into account when building mobile web applications.\nHere's a link to the session abstract:\nhttps://www-950.ibm.com/events/wwe/lotus/lsph2010.nsf/sessionabstract?openform&amp;sessionid=BP212\nThe other session I'm doing is called 'Beyond the Mobile Browser – Building Rich Mobile Applications for Domino.' It's really an extension of the first session. In this one, I'm going to demonstrate how to build several mobile rich client applications that talk to a Domino Database. The assumption here is that although the browser is cool and all – that sometimes the browser isn't sufficient for your application. Perhaps the user needs to manipulate data while disconnected from the network (on a plane for example or when in a business location without wireless coverage) or integrate with other applications on the device (such as the contacts, tasks or messages application). This session is an new and improved version of a session I did at the View Domino Administrator/Developer Conference in Boston earlier this year. I'm going to be building a rich client in Java (for the BlackBerry platform), Windows Mobile and probably Android. I'd like to do iPhone, but I don't have a Macintosh and just don't have the relevant skills right now.\nHere's a link to the session abstract:\nhttps://www-950.ibm.com/events/wwe/lotus/lsph2010.nsf/sessionabstract?openform&amp;sessionid=AD114\nAnyway, both sessions should be high energy, very interesting sessions. Please plan on attending if you're at Lotusphere. The sample code for the applications will be posted to this site in January during the conference.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Review of Beginning BlackBerry Development by Anthony Rizk",
  "date":"Tue Dec 01 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1259712000,
  "url":"/posts/2009/review-of-beginning-blackberry-development-by-anthony-rizk/",
  "content":"On my flights home from the 2009 BlackBerry Developer Conference in San Francisco I had a chance to read Anthony Rizk's Beginning BlackBerry Development. I wasn't one of the lucky folks who received a free copy of the book at the conference – I'd received it in advance of the event and brought it with me to read on the plane home. Anthony did sign it for me at the conference, so that was fun. When I discovered that the book was on its way, I contacted Anthony to find out about his book and see how it compared to mine. It turns out that they're very complimentary – they both address beginning developers, but cover different parts of the topic.\n\nThe book is really good – I enjoyed reading it and learned some things I've always wanted to know. First of all, although the title doesn't say this, the book is a Java book – targeted at BlackBerry developers who want to get started writing Java applications for the BlackBerry platform. It doesn't cover anything about web development and only covers the platform (BES and MDS) very lightly. You should already be comfortable with Java development; the book doesn't cover any of the basics, only the BlackBerry specific stuff you'll need to know to work on the platform. It's a rather short book, only about 240 pages, so don't expect it to cover any particular topic in great detail.\nAnthony wrote the book in short lessons, each tackling a different part of the whole picture. The book begins with defining a little about the platform, how to obtain and install the development tools (chapter 1) then how to build a simple Hello World application (required for any beginning development book) and test/debug it in the simulator and on an actual device (chapter 2). Next he digs into what makes a BlackBerry Java application and some specific features/requirements of the platform (chapter 3). In all, it's a great introduction to BlackBerry Java development.\nOnce you're beyond the basics, the book starts building a sample application that illustrates how to build an application's user interface (chapters 4 and 5). What he does is work you through building a login screen for a sample application then extending it to leverage some features of the platform and also how to tweak and tune the UI components Research In Motion provides to make the application look and feel like you want. While much of the chapters cover topics most Java developers will already know, he addresses the BlackBerry-specific stuff you'll need to understand related to working with the Research In Motion UI Libraries.\nThe next couple of chapters dig into some both standard and unique capabilities of the BlackBerry platform: Storing data (chapter 6), Network Connections (chapter 7) and location based services (chapter 8). For each of these, the BlackBerry platform supports industry standards/specifications (RMS for data storage, HTTP connections for network access and JSR 179 for location based services) but also has some special enhancements or supports additional options to allow you to create more robust applications. These topics aren't covered in tremendous detail, but you leave each chapter knowing exactly what you need to know to begin using these capabilities in your BlackBerry Java applications.\nChapter 9 digs into how to package up your application for deployment (through Desktop Manager deployment, BES Push, OTA Pull or through BlackBerry App World).\nAnthony has been a BlackBerry Java developer for a long time, so he really knows what he's doing and it shows in the book. His writing style is very comfortable and he covers each topic not deeply but well. The book is structured in a way to make it easy to digest each topic before moving on to the next, so as long as you know Java, you should be all ready to go after reading it.\nThe book's got some typos and errors, but if you're an experienced developer you won't have any trouble spotting them and making the necessary adjustments. It's clear that they rushed the book out to get it released in time for the BlackBerry Developer Conference, so it's understandable. Anthony told me he's building a list of these items and will hopefully get them implemented in the next printing.\nIf you're a Java developer and want a quick primer to get you started on the BlackBerry Java platform, this book is for you.\nIf you've been a BlackBerry Java developer for some time, the book may have information you don't already have, but that's unlikely. If you're expecting this to be a heavy duty, deep dive into BlackBerry Java development, you'll be disappointed (but the title should have warned you away anyway). There's still no reason you shouldn't purchase a copy and keep it around to lend to those pesky developers who keep asking you simple questions.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Certification Expiration",
  "date":"Mon Nov 30 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1259625600,
  "url":"/posts/2009/blackberry-certification-expiration/",
  "content":"I was just registering for another BlackBerry Developer certification exam and came across the following notice:\nImportant BCP-210 Exam Retirement/Expiry Notification\nExam BCX-220 is an update to the BCP-210 exam and is currently in beta. When this exam is released in its live format (estimated late November 2009), the BCP-210 exam will be retired and no longer available for testing.\nIndividuals certified as a result of successfully passing the BCX-210 or BCP-210 exam will be required to re-certify by March 31, 2010 to maintain their certification status. As of March 31, 2010, all BlackBerry Certified Support Specialist certifications earned as a result of successfully passing the BCX-210 or BCP-210 exam will expire. If you have any questions about the exam retirement or expiry process, email certification@blackberry.com.\nWhat this means then if you took the BCX-210 exam and passed (like I did), you're going to have to retake the exam in 4 months just to keep any certification you received. Normally I'd rant and complain about this, but since RIM helped with the book and allowed me to participate in the beta for the BCP-210 exam I really can't say too much. It is however not very fair to grant a certification and only a few months later invalidate it. You'd think they'd allow you to remain certified longer than that before yanking the rug out from under you. I'm curious as to what happened (I truly have no way to know) - was the 210 exam flawed in some way?  Only time will tell...\nIf you're thinking about taking the exam, you'd best wait until the 220 exam becomes available - there's no sense taking the exam and having to pay and take it all over agin in just a few months.\nSorry for yet another shameless plug, but several people have already confirmed that the best way to prepare for this exam is to read BlackBerry Development Fundamentals.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "First Amazon Review is In",
  "date":"Sun Nov 29 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1259539200,
  "url":"/posts/2009/first-amazon-review-is-in/",
  "content":"Well, the first review of BlackBerry Development Fundamentals has been posted on amazon.com. Unfortunately it's not a very flattering review. Apparently the reader missed the word 'Fundamentals' in the book's title and expected it to be something else than it is. Just in case you're thinking about purchasing the book - please know that it's a book for new BlackBerry developers, not experienced BlackBerry Developers. It contains everything I know to help a new BlackBerry developer get started with BlackBerry development. It's designed to help a developer understand the capabilities of the platform (both from the server and device standpoint), the limitations of the platform and how to build applications for the device. If you're new, I promise you you'll love it and find it very useful. If you're experienced - you don't need my book and any of the other BlackBerry development books that are coming to market.\nIf you want a real, unbiased review of the book, please read the following reviews. The first was written by an experienced BlackBerry Developer and the second by an experienced BlackBerry guy who wants to be a BlackBerry Developer:\n\nBlackBerry Development Fundamentals Reviewed (notesberry.org)\nReview: BlackBerry Development Fundamentals Book by John M. Wargo (berryreview.com)\n\nIf you're interested in hearing me talk more about where the book fits and more, please read Ben Pijor's interview on port3101.org:\n\nInterview with Author and BlackBerry Developer John Wargo (port3101.org)\n\nIf you've read the book and you find it useful, will you please help me out by writing a review on amazon? I really need people to see more than just that one (bad) review. Thanks in advance!\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Another Review",
  "date":"Sun Nov 29 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1259539200,
  "url":"/posts/2009/another-review/",
  "content":"Peter Strange posted a review of BlackBerry Development Fundamentals to the BlackBerry Development Forums. It's great to see that people are 'getting' where the book fits in the market. You can read the review here.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "A Book Scam on Amazon.com",
  "date":"Mon Nov 23 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1259020800,
  "url":"/posts/2009/another-internet-scam-on-amazon.com/",
  "content":"As you may or may not know, BlackBerry Development Fundamentals was not actually my first book. If you're reading this from my Amazon Author page, then it's easy to see that.\nI was a Soccer (Football for those who know better) Official for about half of my life and on the day I retired and I left my last Referee meeting (it ended up being my next to last meeting, but that's another story I'll probably not share) I decided to write a book for brand new Soccer referees. I'd been a Referee Instructor, worked Professional matches (both Indoor and Outdoor) and traveled all across the US working games so I thought I had a lot of good insights to share.\nI know of many people who 'decide' to write a book but never do, but in this case, I promised myself that I'd actually write the book – and I did! I discussed it with my wife, spent some nights and a week of vacation and finished it. It actually took longer to lay it out in Adobe FrameMaker and go through many review cycles than it did to write it.\nAnyway, I wrote it and it's published - it's called What Now?: The Essential Guide for New Soccer Referees. It's available on amazon.com and not many people have actually purchased it (although it is a great book if I do say myself). It's targeted at brand new Soccer Referees – the ones who walk out of their first Referee clinic with glazed eyes and ask themselves 'What now?' The clinics are so chock full of information and there's so much to know, that new referees leave and just don't know what to do next. The book specifically covers that – starting the minute the clinic ends and taking you through to the beginning of your second game. I thought it was a pretty cool idea and many people who have read it have agreed.\nAnyway, the reason I'm writing about the book here is because of this sort of scam going on at amazon.com that I just can't figure out. The book's on sale on amazon.com through a subsidiary called Book Surge. It's publish on demand, so when you place an order for the book, they dig up the source file, print and bind a copy of the book, stuff it in an envelope (with an amazon.com label of course) and plunk it in the mail. Sounds pretty simple, doesn't it?\nSo here's where the scam comes in – and I have to be honest and say that I really don't understand it. Here it goes…\nYou can buy the book brand new and in perfect shape (Perfect Bound even – it's an industry term) for $14.95US. Seems pretty straight forward. Now, when you go to my book's page here, you'll see that there are vendors selling both new and used copies of the book. Take a look:\n\nNow, what I don't understand is why there are vendors out there selling the book for twice and even almost 3 times the standard price of the book? If you can get the book for $14.95, why would you buy it at $35.00 or more? It just doesn't make sense. Now, if I was famous (I'm not) or if it was a special copy of the book (signed for example, which I know they aren't – I know I haven't signed any), it could be worth more money, but not what these places are charging.\nWhy would there ever be a market for the book at those prices? It's not really selling at $14.95, why would ANYONE think it would sell at an even higher price?\nThe reason I called this a scam is because it just seems like one. There has to be some angle – nobody would actually buy one of the books, so the vendors must be doing it so it looks to buyers that they have a large inventory. There's clearly something weird going on though and I'm pretty sure that Amazon should do something about it. It's not fair to consumers to allow products to be offered at such a ridiculous price.\nDo you think the vendor is just going to buy a copy of the book for $14.95 then turn around and send it to the sucker who paid them double list price? I don't see it happening. Do you think they actually have a used copy of the book? I did send about 60 out to every US State Director of Referee Instruction (and never heard back from any of them), it's possible that one of more of them sold it or donated it to a reseller – but why a minimum of twice list price? That's still not making sense – are people really that stupid?  “hey, look here – I can get a USED copy for only twice what a new one would cost!”\nI sent one of the vendors an inquiry – asking “Why do you think that people will pay more than double the list price for a used copy of my book? It doesn't make sense.” I'll let you know what I hear back although I doubt I'll hear anything. In the mean time, if you're going to buy my book, please buy a new one, it will cost you a whole lot less money. If you want a signed copy, please let me know and I'll sign it and mail it to you for list price plus shipping (still less than these vendors are selling them for). Hopefully Amazon will see this and do some research – it shouldn't be allowed to do this.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Pictures in Our Heads",
  "date":"Fri Nov 20 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1258761600,
  "url":"/posts/2009/pictures-in-our-heads/",
  "content":"I'm a big fan of Robert X. Cringely (although lately he's gotten a little flaky) and I was just reading an article he wrote called 'Pictures in our heads' that discusses the future of mobile computing from a very interesting angle.\nHe points out that desktop computer sales are about to peak (I believe that, but I still love having a honking fast desktop) and shows how mobile devices are advancing at a faster pace than PC's or laptops.Of note was his comment:\n&quot;This means that mobile devices are evolving twice as fast as desktops ever did.  This just about equals the rate at which wireless network bandwidth is declining in price and matches, too, the faster-than-Moore's Law growth of back-end services.&quot;\nand\n&quot;Now just imagine what it says for the smart phones to come.  In another two years they'll be eight times as powerful as they are today, making them the functional equivalents of today's desktops and notebooks.  If only we could do something about those tiny screens and keyboards.&quot;\nHaving just taken a position withing AT&amp;T and being involved in emerging technology, I'm going to be very interested to see what happens in the next few years. My colleagues at RIM ridiculed me when I said people would be embedding bluetooth headsets into their heads so they would not need to hold a device up or could listen to music whenever they wanted - only time will tell if I'm right although I'm pretty sure it will be here soon at least for younger generations.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "How NOT to build a BlackBerry Java Application",
  "date":"Sun Nov 08 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1257724800,
  "url":"/posts/2009/how-not-to-build-a-blackberry-java-application/",
  "content":"As the smartphone app stores become more prevalent and of course all of the app pressure from the iPhone, more and more developers are trying to create these really beautiful and really feature full applications. Apple has done this to all of us and it flies in the face of how you should really build mobile applications.\nThe smartphone has limited battery life, limited processing capacity, limited memory and limited network capacity available to it. It does, it really does – but were being made to believe none of those things are important because of the way all of these apps are being made. A smartphone application, or at least an enterprise smartphone application, should have as few bells and whistles as possible – the application should be crafted so the application is at least good looking, easy to use (without requiring an instruction manual or training) and the user has access to the exact data they need, when they need it and nothing more.\nSmartphone applications should work regardless of whether a network connection is available or not. If can have less functionality when disconnected, but it should continue to work – using the locally cached data available to it.\nI'm at the BlackBerry Developer Conference in San Francisco this week (look me up if you're there – my published will be selling copies of BlackBerry Development Fundamentals and I'm going to be signing copies of my book at the conference Thursday during lunch) and before I left I installed the free conference RIM provided for attendees. I expected RIM to use the Viigo application again like they did last year, but instead I found that they apparently engaged someone else to build this year's conference application. It's too bad, because the Viigo application is pretty cool and has usefulness outside of the conference and this new conference application is pretty horrible. The application is however a great example of how you should NOT build Java applications for BlackBerry devices. Let me explain…\nThe application is installed from the BlackBerry App World which is cool and is what I would expect from any mainstream BlackBerry application released in 2009 and beyond. It's when you go into the application that you notice that the people who developed the application really didn't know what they were doing. The application wasn't crafted for a mobile user to use at the conference; it was crafted to show off the cool capabilities they have built into the application.\nWhen you first launch the application, a splash screen fades in (showing the conference logo), sits there for a while, then fades out again. If I'm an attendee at the conference and I'm trying to look up something (like where I need to be next) this long delay in opening the application just to show me how you can make a cool fade-in effect is a waste of my precious time and places an extra drain on the battery. Think about it, I'm at a conference going from session to session sending emails, making phone calls and generally using my device heavily. On top of that, with the expected 1,000 people at the conference, it's likely that cellular wireless network coverage is going to be in high demand. I don't know if you knew this, but the BlackBerry device (and most smartphones) drain their battery at a more rapid pace when it has difficulty getting or keeping a wireless network connection. So, as I'm sitting at the conference draining my battery at a higher rate because of an overloaded local network, the application is shamelessly wasting even more battery life. Now, don't get me wrong, wi-fi should be available, so I'm not worried about data traffic – but when the voice network gets congested (as I expect it will) batteries start to drain.\nOK, when the splash screen finally fades away and I can get into the application I'm presented with the screen you see below. They've selected a VERY busy background and used these battery wasting scroll-in effects for the menu so it takes even longer before I can begin working in the application.\n![Figure 1\nFigure 1\nAs you scroll from menu item to menu item, the application uses this smooth fade-in ad fade-out for the selected menu item then changes the entire background image (as shown in the following figure).\n\nFigure 2\nOK, so not only do I have a very busy (too busy) background image for the application, I have to wait as the application applies fancy effects to the menu and swaps out the complete background for the application. Yet another waste of my time and a huge waste of device battery life.  Developers should not add screen effects that slow down application performance for the user. If you can implement them without affecting the user, great – otherwise leave them out of your application.\nI'm an older guy and my eyesight has been deteriorating lately (not too bad, but enough to be annoying) and the dark menu against the busy background makes it very hard for me to be able to read the screen without my glasses on. Developers should al",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Internet Scam 2",
  "date":"Sat Nov 07 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1257638400,
  "url":"/posts/2009/internet-scam-2/",
  "content":"I don't know why I like writing about these Internet email scams, but I just do. I think it's because I know people are responding to them (otherwise they would go away) and that just fascinates me.  Here's one I got this morning – it's so stupid that I'm stunned that anyone would even try this approach, but you know what P.T. Barnum said, right?\nHere's the email I got:\n\nFigure 1\nThe good thing is that my ISP recognized the email as Spam (no, Spam is not an acronym, it's a breakfast meat product – why do people type it in all caps?) and modified the subject of the message on its way to me. Anyone receiving this should benefit from those types of services that ISP's provide. \nI forgot to look at the message headers before I deleted the message. If I'd been smart and thought to do that, I'd be able to show you the actual email address behind the email message. It's always a good idea to look at the message headers of any suspect email – it tells you a bit about where the message really came from and what route it took to get to you. Any message from Facebook that started in some Eastern European country is suspect no matter what. Not because Eastern Europe is a dangerous place to get emails from, it's just that Facebook is a US company and it's likely that any message they send me will likely come from a US Server. Right?\nNow let's look at the email address it was sent to: info@mcnellysoftworks.com. Well, I happen to know that I don't have a Facebook account registered using that email address. That's my next clue that it's junk email. \nThe subject of the email makes sense, nothing too scary there (except for that SPAM notification my email server added to the message).\nThe body though, just isn't right. I have to think that if Facebook is sending me email messages, they'll take the time to:\n\nMake sure it looks professional. I'm pretty sure the Facebook logo will be in anything they send to me.\nAddress it to me. They know my first and last name, any message from my bank, Amazon, Facebook, LinkedIn, etc. better be addressed to me by name otherwise I'm ignoring it. Why would they say 'Dear Facebook user' when they could just have easily have said 'Dear John'?\nMake sure it's in English. I don't know about you, but 'Accounts that do not submit the updated account agreement by the deadline will have restricted.' Isn't a complete sentence and was probably written by someone who doesn't use English as a first language.\n\nNow, here's where it gets interesting. So Facebook is a very popular, Internet-based Social Networking site, right? Everything (and I do mean everything) they do is done online, right? So, why would they send me a zipped attachment containing an account agreement? Nope, they'd never do that. Take that a step further and ask yourself, not only would they not send me an attachment, they also wouldn't ask me to launch an executable to access the agreement. If, by the wildest stretch of the imagination, Facebook did send me an account agreement as an attachment, wouldn't you think the the attachment would be a text file, a Adobe Acrobat file (.pdf) or even a Microsoft Word document (.rtf, .doc or .docx)? It's an absolutely ridiculous premise that people would think it's OK to unzip and attachment and execute an executable (I know, redundant) to access an account agreement for the world's biggest Internet site?  Seriously?\nAnyway, I think it's funny that these spammers and scammers are still trying this approach. But, as I said at the beginning, they only reason this would still be happening is if either the scammers are really, really stupid or people are actually following the instructions and launching the attached executable. It has to be the latter and that just scares me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Moving a Joomla Site",
  "date":"Wed Nov 04 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1257379200,
  "url":"/posts/2009/moving-a-joomla-site/",
  "content":"I use Joomla! to manage many of the sites I've built. It's an open source CMS and it's really pretty cool. As I was building blackberrybooks.org yesterday I made a big mistake and thought I'd write about it.\nI host all of my sites on fatcow, they're really great and have some amazing tools site administrators like me can use to manage their sites, install open source tools, create databases, create mail accounts and more. One of the tools is something called InstallCentral that basically points to scripts that can be used to install all sorts of open source tools (content management systems, blogs, galleries, forums, e-commerce stuff and more). It was through this tool that I first discovered Joomla! and although Joomla! is pretty easy to install, I've always just let FatCow's InstallCentral install it.\nAnyway, yesterday I was working on setting up blackberrybooks.org and I launched the installation like I normally do. When it came time to pick the installation folder, I accepted the default and populated the other fields on the installation form as shown in the following figure:\n\nWhat I forgot to pay attention to was that mcnellysoftworks.com actually pointed to a subfolder called 'home' within my FatCow account. That way I can have my 'home' folder and a separate folder for each of the other sites I manage there. So, when InstallCentral installed Joomla!, it dutifully put it exactly where I asked it to be placed and that was '/home/bbbooks'  which is not where I wanted it, I wanted it in a folder called '/bbbooks' off of the root.\nAfter I got the site all up and running and populated all of the book information, I used another cool FatCow tool called 'Domain Pointing Manager' to point blackberrybooks.org to the folder where I thought I'd installed the site. When I fired up the browser to test the redirect, I got a file not found error message. I quickly fired up an FTP Client (I use FTP Voyager https://ftpvoyager.com/ from Rhino Software) and looked for the folder and it wasn't there! Ouch. I looked and looked and looked and could not find the Joomla! files where I thought they were supposed to be. It took me a while to figure it out but I finally did and located the files – right where I didn't want them but right where I'd told the installer to put them.\nRats, what do I do?\nWell, I couldn't tear down the site and reinstall then rebuild in the correct location (I know how I'm supposed to do it, I just forgot to do it) but on principal that didn't make sense to me. I hate completely redoing something – it's just not in my nature.\nI thought perhaps I could just use FatCow's File Manager application to move the files, but I thought perhaps it would somehow not work once I got it moved. Also, I didn't want to have InstallCentral thinking it had an installation where it didn't (my form of OCD) so I couldn't do that.\nAs I thought about it I was suddenly struck by a thought. On a weekly basis I backup all of my sites using JoomlaPack (a free backup utility for Joomla!)- I wondered whether I could use that to backup the site and put it in a new location. I dug out the instruction manual and found to my delight that I could.\nSo, I performed the following steps:\n\nBacked up my Joomla! installation for the site\nCopied the backup file to my local hard drive\nUnzipped the backup file to a temporary folder\nUploaded all of the site's files to the /bbbooks folder on my FatCow account\nLaunched the browser and accessed the site in its new location\n\nIt worked!  Woohoo, it worked! So, I now had the files where I needed them and it was working. One of the reasons it was working was that both instances were using the same database table. I knew though that as soon as I uninstalled the Joomla! instance created by InstallCentral it would empty (but not remove) the existing database. Well, that wouldn't work – when I uninstalled it, I would lose all of my data. So, I went back in and performed the following steps:\n\nPerformed a database backup (because when I uninstall the Joomla! instance, InstallCentral will drop all of the database tables)\nUninstalled the Joomla! instance in InstallCentral\nRestored the database from my local backup\n\nWho'd a thunkit, it worked!!! I got the whole thing moved and the InstallCentral installation list all cleaned up and it's working great.\nI know, I know, I could have used the FatCow File Manager application to just copy the files to the new location then do the second set of steps, but it was fun to see whether JoomlaPack would do what it was supposed to do (I expected it would, but it was fun to find out).\nI wrote this article to help others playing with FatCow and Joomla! but probably also to reinforce in my mind that whenever I install another Joomla! instance using InstallCentral, I need to select the Unix root folder name for my FatCow account rather than the high level domain as shown in the figure.\nI worked on a project a long time ago with a guy by the name of Russ Chung – he was the most me",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "BlackBerry Development Books",
  "date":"Tue Nov 03 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1257292800,
  "url":"/posts/2009/blackberry-development-books/",
  "content":"If you're reading my blog you've probably already figured out that I wrote a book on BlackBerry development called BlackBerry Development Fundamentals. I've been keeping my eye on the market, watching what new books become available (mostly because I wanted to be able to say I published the first book dedicated to the topic (I did)). To make it easier for people looking for books about BlackBerry, just yesterday I launched blackberrybooks.org, a site containing information on all of the available BlackBerry books. As I spent some time this morning populating the site I noticed that even more books were coming out early next year so I thought I'd share a little bit about what I know about these books:\n\nBlackBerry Development Fundamentals: This is the ultimate getting started guide for BlackBerry developers. If you need/want to get into BlackBerry development, this is the book that will explain to you everything that the platform can do, how to optimize your applications for the platform and how to build applications using the free tools available to you. It's not a heavy duty coding book, it's a book about what it does, how it works and how to do it. There's code samples in there (especially for the BlackBerry Java development chapters), but it is more about giving you a base understanding of the capabilities, features and especially limitations of the platform.\nBeginning BlackBerry Development (By Anthony Rizk): Although the title doesn't say this (Anthony said that the publisher was adamant that the title matched their other books rather than say what the book is actually about) this is a BlackBerry Java development book. The book contains everything a developer would need to know to get started with building BlackBerry Java applications. I haven't read it yet (my copy only arrived yesterday) but from what Anthony told me, it was designed to be a series of lessons that help you learn how to build BlackBerry Java applications. Anthony maintains his own BlackBerry development web site called Thinking BlackBerry and just started a software company called Zeebu Mobile.\nAdvanced BlackBerry Development (by Chris King): This book is supposed to be out by the end of the year and is designed to be a sort of sequel to Beginning BlackBerry Development. It is also a BlackBerry Java development book and it covers advanced topics beyond what Anthony covered in his. I'll be writing more about this book on blackberrybooks.org once I receive my copy.\nBlackBerry All-in-One For Dummies (by Dante Sarigumba, Robert Kao, William Petz &amp; Timothy Calabro): This book isn't really a developer book although it is supposed to have some development topics covered in it. It's designed to take a whole bunch of Dummies books and wrap them all up in a single cover. I can't imagine that this book will be useful to anyone other than to a very beginning BlackBerry developer or one just wants to understand a little bit about how it works. Don't expect a book that covers user, admin and developer topics in the same volume to be any good (sorry)\n\nIf you think about it, with the first three books you've got the whole gamut covered - beginning through advanced.\nThis morning I discovered some additional books that will be out early next year, here's a rundown:\n\nLearning BlackBerry Game Development (by Carol Hamer &amp; Andrew Davison): This book is also a BlackBerry Java development book and is dedicated to game development. It should cover the Java specific topics that apply to BlackBerry development.\nProfessional BlackBerry Java Development (by David L. Williams): Yet another BlackBerry Java development book. I expect that this one will compete pretty closely with Beginning BlackBerry Development.\nBeginning Smartphone Web Development: Building JavaScript, CSS, HTML and Ajax-Based Applications for iPhone, Android, Palm Pre, Blackberry, Windows Mobile and Nokia S60 (by Gail Frederick): This one isn't a dedicated BlackBerry development book, but covers web development for smartphones.\nPro Smartphone Cross-Platform Development: iPhone, Blackberry, Windows Mobile and Android Development and Distribution (by Sarah Allen &amp;Vidal Graupera): This book seems to cover native cross platform development for smartphones. It's going to be an interesting read because there's no way to build cross platform native applications anymore - the iPhone and Android killed that of all of us (I'll write about this in a little while). I'm not sure what they're going to tell you since the only cross platform application technology available on the devices they list is browser development. We'll see what it says when it comes out.\n\nWell, that's it - I'm sure glad I decided to write my book when I did (I started writing December 1, 2008) - it looks like a whole bunch of cool books are on the way and I'm sure more will follow. Right now I know my publisher is looking to write a BlackBerry Java development book and I'm interested in working on it. If you know of a heavy ",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Joomla FTP Settings",
  "date":"Mon Nov 02 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1257206400,
  "url":"/posts/2009/joomla-ftp-settings/",
  "content":"I've been catching up on my Joomla reading; I picked up a few Joomla books over the last few months and I had some time the other day flying forth and back from Houston for a job interview so I took the books with me. One of the things they mention in some of the books is that to avoid file ownership problems, you should configure Joomla to use FTP to upload files. I have been trying to get the Joomla Content Editor (JCE) installed (with NO success) so I thought I'd try this configuration option to see if it helped me with my JCE problems.\nI pulled out Joomla! 1.5: A User's Guide: Building a Successful Joomla! Powered Website (2nd Edition) and looked up the page covering FTP settings and found...nothing. Just a screen shot and no explanation of how this should actually be configured. So, I created an FTP account for Joomla and went into the Joomla Server configuration to enable the settings. Here's a picture of the settings page:\n\nFigure 1\nI had the FTP account configured, but I couldn't figure out what to do with the 'FTP Root' field. Originally I configured the FTP account so it's root was the root folder for the particular Joomla implementation. I did this assuming that Joomla would want to login and see it's own folder structure. Nope, wrong approach. What I had to do was configure the FTP client to use the domain's root folder as it's root folder then leave the FTP root folder blank in the dialog shown above. That way, both Joomla and the FTP login are looking at the same folder structure.\nIt took me some trail and error to figure this out. I mentioned the book wasn't any help and the field help didn't tell me anything - so that's why I decided to write about it here.\nI still can't get JCE installed. the tool's web site says I should use Joomla's installation tools (doesn't work) and the manual installation instructions if the automated install doesn't work. The problem is that the manual instructions refer to files that I can't seem to find in the packages I downloaded from their site. I'm at a loss and when I tried to access the forums today I got a page not found error. If you can help me get JCE installed into a Joomla instance please let me know.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Drupal Problems",
  "date":"Mon Nov 02 2009 19:00:00 GMT-0500 (Eastern Standard Time)",
  "date_timestamp": 1257206400,
  "url":"/posts/2009/drupal-problems/",
  "content":"I started playing with Drupal a while back because I wanted to see how one of the other Open Source CMS worked. I'd been thinking about building a site called blackberrybooks.org and decided to use Drupal for it.\nI'd purchased a copy of Using Drupal and noticed that it contained a chapter on building a product review site, so I knew I had exactly what I needed. I dug into the book and carefully crafted the site I wanted and when it came to the section where I was building the views I'd need to display the book listings, nothing worked. Every time I followed the steps in the book (step by step, I promise) I'd reach a point then start getting errors.  Drupal has an automatic update notification feature, so the site sent me an email letting me know that there were updates available for the Amazon plug-in I was using so I installed the updates and tried again - no luck.\nThe problem with Drupal is that although there are a ton of plug-ins available - very few of them (or at least very few of the ones I was using) have any sort of documentation. It's too bad, but as you probably know geeks just don't like writing documentation.\nI gave up and built the site using the Book Library module for Joomla.  It took me about an hour to completely build the site in Joomla. I hope I get another chance to try Drupal again - it's an amazing CMS, much more flexible and tunable than Joomla.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "Search Engine Friendly URLs",
  "date":"Thu Oct 29 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1256860800,
  "url":"/posts/2009/search-engine-friendly-urls/",
  "content":"I've been doing a lot of reading lately about Joomla! and I've been tweaking this site (and the BlackBerry Development Fundamentals site as well). I haven't been getting very good traction with the search engines, so I installed a Search Engine Friendly module tonight. Everything seems to be working OK, but I still need to learn some things about this system. The issue for you is that any links you've bookmarked into the site may no longer work (I'm not sure). You'll need to grab new ones (until I can figure out how to setup aliases).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Programmatically Enabling JavaScript in the BlackBerry Browser",
  "date":"Sun Oct 25 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1256515200,
  "url":"/posts/2009/programmatically-enabling-javascript-in-the-blackberry-browser/",
  "content":"One of the most interesting things I learned while I was writing the book was how to enable JavaScript programmatically within the BlackBerry browser. As RIM reviewed the chapters, several people commented on how, even if JavaScript was turned off in the browser, it could be enabled programmatically. I searched and searched for information about how to do this, but couldn't find anything until I finally begged someone from RIM to explain to me how to do it. Here's how it's done:\nIn the NoScript section of an HTML page, put in some JavaScript. It doesn't have to be script that does anything, it just has to be JavaScript. When the browser encounters the JavaScript, it sees that it's disabled and prompts the user to enable it.\nHere's a sample web page that enables this:\n\nWhat's interesting about how this works is that MDS will normally process the HTML page and remove any content not supported by the browser - it doesn't make any sense to send anything to the browser that the browser won't recognize. So, it the HTTP Accepts header indicates that JavaScript is not enabled, then MDS will remove all of the JavaScript code from the page. Since JavaScript isn't expected to be in the &lt;NoScript&gt; area of the page, MDS ignores it and delivers that script to the browser. When the link is clicked, the browser performs its check and prompts the user to enable JavaScript. \nPretty cool, right?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Quick Access to BlackBerry Server Docs",
  "date":"Wed Oct 21 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1256169600,
  "url":"/posts/2009/quick-access-to-blackberry-server-docs/",
  "content":"I came across this URL a while ago and thought I'd share it with all of you. So many times you're looking for documentation on RIM's web site and you have to hunt around to find what you're looking for. When looking for a particular server document (this is for the BES, not the development tools) I usually used search and drilled down from there. Well, there's a very useful URL every admin should have - it's blackberry.com/go/serverdocs.\nAt this URL is a very organized summary of all server documentation categories as shown below. The most useful part of this for me has always been to pick one of the BES platforms - that page that appears next shows the most recent versions of the BES docs for the selected platform and has a drop-down list containing all versions. You can then make a selection from the drop-down and see every doc related to the selected version. This is very useful when you have to support multiple BES versions (like I know my friends at Vox Mobile do every day) and want to find the right doc right away.\nEnjoy the tip!\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Domino Header Dump Sample Application",
  "date":"Tue Oct 20 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1256083200,
  "url":"/posts/2009/domino-header-dump-sample-application/",
  "content":"Have you ever wanted an easy way to see what HTTP Header and CGI variables were available to a Domino Wev Server? I know much of what's available is documented, but when I started learning about BlackBerry web development, I wanted a way to be able to see in real-time what the Domino server knew about the BlackBerry device connecting to it. To help me figure this out, I created a little sample Domino database that dumped a bunch of information the Domino Server knows about a User-Agent (the browser) back to the browser screen making the request.\nHere's a sample screen shot from a BlackBerry device illustrating what the application looks like:\n\nI just posted an article about the application and the Domino database to my BlackBerry Development Fundamentals site. Check it out when you get a chance (only if you're interested of course).\nThere's a piece of the application that shows what JavaScript information is available to the BlackBerry Browser - I noticed while I was working on the book that it isn't working on BlackBerry Device Software 4.6 and higher - sorry, but I haven't gotten around to fixing it yet.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Another Internet Scam",
  "date":"Sun Oct 18 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1255910400,
  "url":"/posts/2009/another-internet-scam/",
  "content":"Continuing with my current theme of writing about internet scams, another one made its way into my inbox this afternoon. Technically it's not necessarily a scam, they may actually offer the service, but it's an unsolicited email (and currently against US law, right?) that an uninitiated person would read and say 'holy crikey, I'd better send this in...'\nThe subject of the email was: &quot;Domain Notification: JOHN WARGO This is your Final Notice of Domain Listing&quot; - something that will make its reader think that they've missed some sort of deadline and are about to lose something. If you look at the email (that's the entire email body shown below) they certainly made a big effort to make it look professional and authoritative. If you printed it, it would look just like a business form, lending it even more credibility. When you start to read it, it's clear that it's a solicitation, but I'm not sure many people would read it. It's deliberately designed to deceive the reader but they're doing it, so it must be having some sort of success.\n\nFor the record, soccerrefs dot org is a site I've owned for it seems like forever. I built a Domino-based referee schedule management system and had it running for many years on this site. Even through I'm long retired as a Soccer Official, I recently setup a Soccer Referee forum on the site using phpbb, an open source bulletin board system. As soon as I get some time, I'm going to probably move it to vBulletin and do some advertising to generate some traffic and see what I can make with it.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Internet Scams",
  "date":"Thu Oct 15 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1255651200,
  "url":"/posts/2009/internet-scams/",
  "content":"I love getting scam emails - I don't love it because getting the messages is fun, it's actually pretty annoying (as I'm sure you all know). I use Qurb to block spam messages in my personal email account, I've found it to be very reliable - which is easy when you build a whitelist product. No false positives when everything is done against a whitelist.\nAnyway, a while back I got this really interesting scam message indicating that it was from the IRS offering me access to a bigger refund if I filled out a form. A quick dissection of the email showed that it had nothing to do with the IRS (I wasn't fooled for a second, I promise). Yesterday I got the following email:\n\nFigure 1\nI truly wonder how many people fall for these types of emails. If you're not technical, you probably think nothing of it and click away. Knowing that I'm the only person at McNelly SoftWorks (it's my home business) it was easy to know that I didn't send the email message. I give the spammer/scammer credit for trying to make a pretty believable email message. If you think about it though, anyone who thinks about it should be able to easily see through the facade, right? What company would identify their support organization by their internet domain? If the message was from McNelly SoftWorks rather than mcnellysoftworks.com it's possible that it's a real message - but any company that sent the message would know to use the company name. So, even though the spammer/scammer appeared smart at the start, it's clear that they didn't think about what they were doing.\nI've started making a habit of looking for my first name in any suspect email message. If it's addressed to my email address, I know immediately it's a scam. My bank and other companies I do business with know to address me as John. Any ebay, amazon, facebook email has got to have my name in the salutation (not my email address) in order for me to read it.\nOf course, if you look at the code behind the link, at first pass it does seem like a valid URL because it begins with mcnellsoftworks. Anyone who was looking but not paying attention would miss the .somescammercomain.com appended to the end of the URL. Most people look at the start of the URL to see if it's valid and as soon as they see what they're expecting, they stop reading and move on. You have to be especially diligent when investigating these types of spam.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Why Norton Internet Security is Dead to Me",
  "date":"Tue Oct 13 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1255478400,
  "url":"/posts/2009/why-norton-internet-security-is-dead-to-me/",
  "content":"I've been a HUGE Norton fan since the beginning of my career. I loved Norton Utilities and have used Norton Antivirus (all of its different flavors) ever since I got on Windows. I have to say though that I'm done with it, just done.  I kept updating my subscription every year, but this last version (2009 I guess) was absolutely horrible. I had to disable so many of its features to be able to use my HP network printer and FireFox was never the same after one of its updates. With FireFox, when I start it up on my desktop, it takes several minutes before it will respond to anything I do. It's not like that on any other machine I use, but only on the one running Norton Internet Security.\nWell, my subscription ran out a while ago and the final straw for me was this:\n\nIt's telling me I need to renew, but it's giving me a ridiculously limited number of options. Instead of letting me say 'don't bother me again' or 'remind me in a week' - the only options available to me are buy now or remind me tomorrow. I was trying to decide what I wanted to do with this, so I had to fire up Task Manager and kill the task to get it to stop reminding me every day. As soon as I reboot my machine, it starts reminding me again and again and again. Enough already - it's unfair to consumers to be this relentless; all it's doing is making me want to use somebody else's product. Now, I happen to own a 5 pack license for Symantec antivirus, so I'm going to switch to that. If I didn't already have that license, I would likely purchase some other product.\nIt's too bad they don't think of their customers when they do stuff like this - it's better to be accommodating (which is what I expect) than annoying (which is what I got).\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "BlackBerry Development Fundamentals",
  "date":"Tue Oct 13 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1255478400,
  "url":"/posts/2009/blackberry-development-fundamentals/",
  "content":"For those of you who are waiting for an update on my new BlackBerry development book called BlackBerry Development Fundamentals, I thought I'd let you know that it's almost done. I approved the final cover today (although we're waiting to hear back from RIM to see whether they have an issue with using the BlackBerry Curve 8900 device image on the cover) and I'm staring at the final manuscript - giving it one final review. The plan, as I understand it, is to finish the manuscript this week (Friday) and send it to the printer. It's expected to be out of the printer and in stock in the warehouse in about three weeks. They've got some little changes to make based upon my review this evening and apparently they're working on the index in parallel. I think, but I'm not sure that I'll be holding a printed copy of the book in my hot little hands in about a week. I can't wait.\nWe ended up not having enough room for all of the sample applications and the book's two appendices, so they'll all be up on the book's web site. The book weighed in at about 600 pages which was way more than the publisher bargained for. By removing some screen shots and moving some of the content to the book's web site, we got it down to about 450 pages. Still a lot of content when you look at it and I'm still amazed that I wrote so many pages. It was the most technical writing I've ever done (and I've done quite a bit of technical writing in my life). All told, when the book goes to the printer on Friday, it will have been 10 months and 15 days since I wrote the first word of the first chapter.\nLocal BlackBerry expert Ben Pijor asked to interview me for an article in an online publication, so I finished that up yesterday morning - expect to see it on or about the time the book pops into the warehouse. His questions were spot on and I really enjoyed answering them. Gave me a chance to give my thoughts on the BlackBerry space - I may even have made a prediction or two, who knows if they'll come true.\nIf you happen to be attending the BlackBerry Developer Conference, look me up. I'll be there attending sessions (nope, I didn't get selected as a speaker) and the publisher will likely be there with a stack of books for sale.\nHere's the full cover in case you wanted to look at it:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "The Presidents BlackBerry",
  "date":"Tue Oct 06 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1254873600,
  "url":"/posts/2009/the-presidents-blackberry/",
  "content":"I've always been a little perplexed about everyone freaking out about Obama's BlackBerry. It always surprised me that everyone was writing articles about how he had to give up his BlackBerry because of security reasons.  Security reasons? It's the most secure mobile device in the market - how could there be security concerns? The headline of every single article I read referenced said security concern but didn't really give the details. It just didn't make sense.  Let's think about it a bit.\nThe device is so freaking secure that it verifies the security signatures of the OS and the application platform when it starts up. No concern there, right? If a signature was invalid, the device would brick – not even complete the startup process. Even if someone could get their hands on the device, it wouldn't work unless the person who mucked with it had access to the internal signing keys and algorithms that Research In Motion uses in its manufacturing process. I'm pretty sure it's in Research In Motion's business plan to protect them at all costs – any failure on this front and the BlackBerry device couldn't be used by any government in the world and any security conscious company. Nope, no worries there.\nAn administrator can configure the device so everything is encrypted on the device using US Government approved encryption protocols. No concern there, right? I remember reading somewhere that It’s even so encrypted that when certain critical information such as a password data is held in memory chips that it’s encrypted there – so if someone got their hands on his device and hooked it up to a logic probe – all they would get is the encrypted version of the data. Oh, by the way, the data is encrypted using keys unique to the device - so there’s no reverse engineering one device and using the discovered keys on another device.  They keys are renegotiated periodically too and there’s even a session key that’s created for every single message sent to/from the device.\nYep, pretty secure so far.\nAll of the data transmitted between the President’s device and the White House’s BlackBerry Enterprise Server (BES) is encrypted (both ways) using US Government approved security protocols. At no time is any of his data unencrypted until it gets INSIDE of the White House firewall. Yep, no worries there either, right?\nI’m not sure about Verizon and Sprint’s network, but on EDGE (the network used by AT&amp;T and T-Mobile in the US), the transmitted data is encrypted during transmission. Yep, even though the BlackBerry encrypts it, the wireless carrier encrypts it again on the wireless network.  No concerns there, right? It’s not US Government approved encryption, but it’s an encryption on top of a US Government approved encryption protocol. Ya, it’s probably OK.\nSo, what’s the big concern?\nI’m not sure if this is really it, but I have been reading BlackBerry Planet: The Story of Research in Motion and the Little Device that Took the World by Storm (Wiley) by Alastair Sweeny and came across something interesting.  The book is supposed to be about the history of Research In Motion, but so far, it’s a big discussion of BlackBerry addiction and about Obama’s issues with the BlackBerry. Not what I expected. I already know about BlackBerry addition and honestly, except for this particular article, I really don’t care about the President’s BlackBerry device woes.\nAnyway, I digress – so in the book, he said:\n\nThe Secret Service and the National Security Agency say that the main danger to the president lay with the cellular radio in the device, which constantly syncs with nearby wireless networks so calls can be routed to the phone. If bad guys ever got access to the cell phone systems that handled Obama’s BlackBerry, they might be able to ping his smartphone to a wireless tower and track his movements. Or they could scan cellular frequencies over several days to triangulate his exact position, even down to one of several identical limousines, even though they could not decode the AES-128 encrypted BlackBerry data.\n\nHaving just received certification as a BlackBerry administrator (BES 4.1 and 5.0 thank you), I happen to know that it’s 256-bit key, but that’s not important right now. AES has a fixed block size of 128 bits, but uses a 128-bit, 192-bit or 256-bit key. I’m pretty sure the White House has selected the 256-bit key; if they haven’t, they’re just not thinking.\nOK, anyway – so someone interested in doing something bad to the President wants to know where he is.  Hmmm, interesting. So, the assumption is that Obama has a BlackBerry and somehow he’s identifiable. Well, he’s surrounded by people who have BlackBerry devices, so how do you identify him out of all of the devices that are around him? You know his staff carries them, his wife carries one, it’s likely that the Secret Service detail carries them. How do you really know it’s him? Well, the premise I guess is that the criminals have gotten access to the mobile equipment (I won",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Development Links",
  "date":"Mon Oct 05 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1254787200,
  "url":"/posts/2009/blackberry-development-links/",
  "content":"Several people have asked me recently for links to different BlackBerry development-related resources. Well, I started building a repository of information about BlackBerry development-related topics - I'm going to launch the site on November 1st, stay tuned for additional information.\nAs I worked on the book, I found different articles on RIM's web site and elsewhere that helped me learn the topic better or reinforce some of the content. At the end of each chapter, I added an Additional Resources section that listed each of these links. One of my reviewers from RIM suggested that I post those links online so they will be easier to access by the book's readers. I setup a special section of the book's web site and posted all of the links last night. You can access the links at bbdevfundamentals.com. I'll be adding more links as I uncover them.\nAlso, RIM recently removed all of the Developer Journal issues from their web site. The Developer Journal was a cool publication because the topics were covered thoroughly in long articles. They were full of pictures and source code. I really loved them and it was through them that I learned most of the nitty gritty details about how some of the technologies worked. I've been told that the Journal articles have been made available as Knowledge Base articles - but I haven't checked to see if they all made it. Even so, the kbase articles are usually very short, so there's no way the full content from the Journal articles made it over. I have copies of most of the issues and I'm toying with the idea of posting them to this site or to bbdevfundamentals.com. Let me know what you think.\nHere's the cover for Volume 2, Issue 1 from 2005 - Looks like good stuff, huh?\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Domino & BlackBerry Java Applications Part 3",
  "date":"Sat Oct 03 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1254614400,
  "url":"/posts/2009/domino-&-blackberry-java-applications-part-3/",
  "content":"Introduction\nNote: removed obsolete attachments November 11, 2022\nIn Part 1 in this series, I showed how to build a simple Domino Web Service that performed a lookup against a contact database built from the standard public Domino Directory template (pubnames.ntf) and in Part 2 and Part 2.5 I demonstrated how to build the Java stub class that can be used to consume the web service.\nIn this installment, I'll demonstrate how to build a simple Java application that uses the generated code to access the web service. At this point, you'll need:\n\nA Domino server hosting the database provided in Part 1. The server must be running the HTTP process and the database ACL must be configured with the appropriate access.\nThe generated class files for the service. These files were generated in Part 2.\nA functioning BlackBerry Java Development environment configured on your system that includes the appropriate Sun Java Development Kit (JDK) plus the appropriate BlackBerry Java development tools (either the JDE or the JDE Plug-in for Eclipse and the appropriate JDE Component package installed). Refer to the BlackBerry Developer's web site blackberry.com/developers for information on how to download and configure these tools. The ability to consume web services using JSR 172 was added in BlackBerry Device Software 4.3, so be sure you are using the right tools (version 4.3 or higher).\n\nI'm going to assume you already know how to build a BlackBerry Java application – there's no time to dig into all of that before getting into the meat of this article. If you haven't worked with the BlackBerry Java development tools then you should either buy my book (bbdevfundamentals.com) or spend some time on the BlackBerry Developer's web site getting up to speed before continuing.\nBuilding the Application\nAttached to this article is a zip file containing all of the code for this application. If you extract the files, you will see a folder structure similar to the one shown in Figure 1. In the source folder you'll find the domdirlookup files generated in the previous installment and the contactLookup folder contains the source files for the application. The application's pretty simple – it consists of three Java class files which will be explained below.\n\nFigure 1 – Project Folder Structure\nStart your development tool of choice (for me it's Eclipse) and open the project; you should see a screen similar to the one shown in Figure 2.\n\nFigure 2 – Eclipse IDE\nThe main class for the application is the ContactLookup class defined in the contactLookup.java file in the project. There's nothing special about this class, it just defines a standard BlackBerry UiApplication called ContactLookup that creates and displays the ContactLookupScreen  screen as shown in the following code:\n\nOnce it creates and displays the screen, it calls the application's enterEventDispatcher method which allows the application to respond to keyboard events and other interesting stuff any BlackBerry application has to do.\nThe ContactLookupScreen is defined in the ContactLookupScreen.java file in the project. This is where all of the interesting stuff happens.  Take a look through the following code then I'll explain what's happening at the end.\n\nThe source begins with a bunch of includes that add the libraries needed by the application. Of special notice are the stub libraries that were generated for this application:\n\nWith these classes imported, the application now has access to the objects needed to talk to the web service.  In the ContactLookupScreen class, some objects are created that the application needs; mostly a string constant and the BlackBerry fields used on the screen.  You should also notice the following:\n\nIt defines an object that instantiates the capabilities provided by the stub class. It's through this object that the remainder of the code has access to the service.\nIn the constructor for the ContactLookupScreen, the text and fields are added to the screen. The callback method is set to allow the listField to be able to draw itself.\nThe makeMenu method defines the menu items available to the program. It's called whenever the user presses the menu button on the BlackBerry device.  Notice that the 'Get Contact List' menu item is only added if there's something in the editSearch field (it's non-blank) and the 'Get Contact Details' menu item is only added when there's an item selected in the list of contacts (the editList field). It actually took me a little while to figure this one out. When you select an item in the list, the index for the selected item changes when you scroll off the list to access another field on the screen. If you scrolled up, then getSelectedIndex returns 0 and if you scroll off the bottom of the list, getSelectedIndex returns one less than the total number of items in the list. The result of this then is that you can really only tell if an item is selected in the list when the list actually has focus.\nOnce the screen is all setup, it",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Change in Status",
  "date":"Mon Sep 28 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1254182400,
  "url":"/posts/2009/change-in-status/",
  "content":"I recently had a change of employment status and I thought I'd write about it here just in case anyone out there knew of someone who had a need for my skills either as a contract worker or full time employee.\nI've been a professional software developer since…well, for a very long time. I started out writing software programs to automate Physics experiments for the University of Akron then branched out into consulting, working for several different firms until I got my job at Research In Motion. \nI became a Novell Certified NetWare Engineer then Novell Certified NetWare Instructor. When I began my Lotus Notes career – I quickly became a Lotus Certified Notes Instructor (one of the first batch certified outside of Lotus). Because of this, I spent a great many years as a full time instructor and finely tuned my presentation skills.\nMy first big accomplishment was an IBM Beacon Award for Biggest Business Impact in 1997 for an application I helped design for Key Bank. We designed and built a system for managing the merchant setup process for credit card processing. The system we built decreased the merchant setup process from 12 to 5 days and involved a very complicated series of integrations with mainframe-based systems all over the US. It was an expensive application to build, but generated a significant return on investment for the bank.\nI've created several commercial software products using Borland (now Embarcadero) Delphi as well as Lotus Notes/Domino.  The most successful Domino one is a product called Automated Deployment Toolkit (ADT) for Lotus Notes. It was an IBM Beacon Award winner in 2002 in the Best Tool/Utility category. It's a product that is still sold today and has been a very successful product for Wolcott Group. For ADT, I did all of the initial product development – building it into a full, commercial product before bringing on additional developers to help maintain and support the product. I was ultimately responsible for development, sales, support, documentation and managing our relationships with partners including IBM (ADT's biggest reseller).\nI created ConfigSave for Lotus Notes – a tool that allowed you to save and restore Notes configurations and easily switch between configurations. In 2002 it won the Lotus Advisor Magazine award for Cool New Tool. I also created ClientSync – a more reliable competitor for the roaming capabilities IBM added to Notes in an earlier version.\nMy favorite commercial application I created is a product called Official's Record Keeper (ORK) – an application for managing all of the data a sports official needs to track. There's a free trial version available for download or it can be purchased here. If you know of any sports officials, please send them that link.\nAs an employee at RIM, I worked with AT&amp;T to support their customers with building BlackBerry applications. I regularly educated customers on the capabilities of the platform and made sure they had everything they needed to build these apps. I became then a subject matter expert on the capabilities of the platform and the tools available to build the apps.  It's these skills that prepared me for writing the book. My enterprise application experience gave me just the right skills to understand exactly what they were going through. I applied the same customer service attitude I used with my software products to make sure every customer was taken care of.\nThrough all of this, I became a very detail oriented and reliable project and product manager, writer and presenter. As I mentioned, I'm looking for contract work immediately – either project management, Domino, Delphi or BlackBerry development or delivering training classes.  I'd be most interested in doing BlackBerry development work (a bonus but not a requirement would be for it to be on Domino).  For the long term, I'm looking for a position leveraging any of my skills. I'm ultimately interested in becoming Director of Mobile Development for the right company but will do any type of work as long as it exercises my brain, leverages existing skills and/or helps me gain new skills.\nIf you know of anything or hear of anything, please let me know – you can use the 'Contact Me' link in the navigation area on the left to contact me.  Thanks for listening (reading).\nI had a conversation the other day with my good friend Rocky Oliver. He's in the same boat as I am and is getting back online. Check out his site when you get a chance.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Delphi",
  
    "Microsoft Windows"
  
  ]
  },

  {
  "title": "Domino & BlackBerry Java Applications Part 2.5",
  "date":"Sat Sep 19 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1253404800,
  "url":"/posts/2009/domino-&-blackberry-java-applications-part-2.5/",
  "content":"I've been getting a lot of questions and comments about the article series (which is great, keep them coming). I got some questions from Brendan yesterday and it was clear that I really didn't cover a very important part of the stub generation process. It's not that I missed it; it's just that I was primarily trying to demonstrate something and didn't cover all of the background information you would need to use this process with your web services. \nIn the example I've provided with this article series Part 1 and Part 2, I've deliberately selected a base web service that's simple enough to be easily consumed using the capabilities provided by JSR 172. Since the specification (yep, it's not a 'standard' as was pointed out last week) was designed for mobile devices, its designers deliberately selected a limited number of data types it would support thinking that it would reduce the potential load on devices and cover a majority of implementations.\n\nWhen I created the service, I created it with the knowledge that the Sun tools for creating the stub program only supported certain data types and I made sure I used them. The problem arises for those of you who want to build BlackBerry applications that consume web services that were not built with mobile users in mind. Let's dig into the detail...\n\nHere are links to all of the articles in the series:\n\nDomino &amp; BlackBerry Java Applications - Part 1\nDomino &amp; BlackBerry Java Applications - Part 2\nDomino &amp; BlackBerry Java Applications Part 2.5\nDomino &amp; BlackBerry Java Applications Part 3\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Domino & BlackBerry Java Applications - Part 2",
  "date":"Sat Sep 12 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1252800000,
  "url":"/posts/2009/domino-&-blackberry-java-applications-part-2/",
  "content":"Introduction\nIn the previous installment in this series, I showed how to build a simple Domino Web Service that performed a lookup against a contact database built from the standard public Domino Directory template (pubnames.ntf)\nFirst a Little Background\nI should probably explain that the BlackBerry Platform added support for JSR 172 with the release of BlackBerry Device Software 4.3. It's JSR 172, the J2ME Web Services Specification, which gives BlackBerry Java applications the ability to easily consume web services. You could do the work without using JSR 172, using something like kSOAP 2, but then you:\n\nWouldn't be using a standard\nWould be relying upon an ancillary library to do the work\nWould have a larger application to deploy since your application needs access to all those extra library classes\n\nAnyway, if you ask about this topic on the BlackBerry forums, you'll receive responses that say JSR 172 is junk and you should use kSOAP 2 and others (like me) who will tell you it's pretty easy and you should just use the stuff baked into the BlackBerry platform. Use the stuff that's baked into the BlackBerry platform – it's going to be much easier for you all around.\nSo, the way this JSR 172 stuff works is you download the Sun Java Wireless Toolkit for CLDC and use a little utility that comes with it to analyze your web service's WSDL (web service description language) file and build a Java  stub class your Java application can call to consume the web service. Building the stub takes just a few minutes and calling the stub from your Java application is very easy as well.\nGetting Started\nTo get this process rolling, go to Sun's web site and download the Sun Java Wireless Toolkit for CLDC – the link is provided in the previous paragraph. After you have downloaded the package, run its installation program to install it on your local hard drive. As someone complained on the forums last week, it's a whole lot of stuff for that one little utility. Unfortunately that's true – the toolkit has a whole bunch of tools and utilities in it, we're only using a very small part of it. I don't know of any other way to get this to work than to just install the whole thing and live with it. After you install it, you'll find a folder for the toolkit off the root of your system's hard drive as shown in the following figure.\n\nFigure 1\nFortunately it also puts the shortcuts you need onto the Windows Start menu right where you expect them to be as shown in Figure 2.\n \n\nFigure 2\nGenerating the Java Stub\nNow that you have the toolkit installed, it's time to build the Java stub you need to consume the service. For this part of the process, you must make sure that the database containing the web service is on a Domino server and the ACL is set correctly. You will also need to make sure that the Programming Model and SOAP Message format are set correctly in your web service. Refer to Figure 4 in the first installment in this series for information on how the service should be configured.\nTo make sure your service is working, you should open the service's WSDL in the browser using the following URL:\n\nBe sure to use the correct server name, database file name and service name for your implementation of the service. For my test environment, the WSDL URL looks like this:\n\nWhen I paste this URL into the browser, I will see the following page (or something similar):\n \n\nFigure 3\nNote that some browsers such as Google Chrome don't know how to render WSDL files. When I opened the same URL in the Chrome browser, all I got was a blank page.\nOnce you have a working WSDL URL, you're ready to generate your stubs. In the Start menu folder for the Sun Java Wireless Toolkit (shown in Figure 2) select the 'Utilities' shortcut. Windows will open a screen similar to the one shown below:\n \n\nFigure 4\nScroll down and select the item labeled 'Stub Generator' and click the 'Launch' button. The stub generator program will open as shown below:\n\nFigure 5\nIn the dialog, paste the Domino WSDL file URL into the 'WSDL Filename or URL' field on the form. You DO NOT want to navigate to a folder where you have exported the WSDL from the database – an exported WSDL does not contain the destination information the stub program will need to locate the server and database file name containing the web service. \nFor the 'Output Path', specify a folder location on your hard drive where you want the stub class files created. For 'Output Package' specify the package name you want to use for the stub class. In this case, I'm saving the output to c:\\dev\\java and the program will create the necessary subfolders to match the output package (com.johnwargo.domdirlookup).\n \n\nFigure 6\nThe program will gyrate for a few seconds and inform you that the process completed. When you open Windows Explorer and look at the output path, What you'll find is a complete folder structure shown below:\n \n\nFigure 7\nNotice that the stub files were created in c:\\dev\\java\\com\\johnwargo\\domdirlookup – the",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Development Webinar Summary",
  "date":"Thu Sep 10 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1252627200,
  "url":"/posts/2009/blackberry-development-webinar-summary/",
  "content":"I attended the the BlackBerry Web Development webinar today and it was interesting. they went through a good concise overview of web development then dug into the new web development tools. I'm always surprised though that the internal developers from RIM NEVER do live demos. Whenever they want to show how any of the technology works, they'd always fire up a recorded demo and play it. What's the fun in that? When I demonstrated the tools, I always did it live. \nAnyway, when the session wrapped up, there were a whole bunch of questions people sent in. Some were kinda lame (sorry) but some were really good. Mike Kirkup hopped on for the Q&amp;A session and jumped in on some of the more political questions.\nWhat I heard was:\n\nWhile RIM won't say it, they're going to support Flash. What I want to know is when the Mono implementation comes? I'd be happy to work on that project!\nMike finally received 'approval' to share some of the deployment numbers with the world. Things like what's the distribution of BES across supported messaging platforms (Sorry Domino folks, you're at about 15% and going down) plus what's the distribution of devices deployed in the market. So many developers have to guess which devices to target for their first applications - soon we'll know. Mike said the numbers would be in his presentation at the conference then posted to the blog soon after. Nothing like having permission to release something then holding on to it for two months so you have something big to put into your presentation at a conference.\nLots of big announcements coming at the developer conference in November.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Domino & BlackBerry Java Applications - Part 1",
  "date":"Sun Sep 06 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1252281600,
  "url":"/posts/2009/domino-&-blackberry-java-applications-part-1/",
  "content":"Introduction\nWhen I worked at Research In Motion and after, I've presented at Lotusphere and the View Domino Developer Conference on how to access Domino applications from BlackBerry devices.\nOf course, the lead approach was to use the browser to access mobile friendly Domino applications. It's not a very exciting demo though – you take a domino database and scrunch it down so it fits the smaller screen and uses rich media sparingly.\nThe other option I discussed was to create Web Services in a Domino application then use Research In Motion's MDS Runtime technology to access the operations exposed by these services. It was a truly amazing demonstration to illustrate the web service then build a rich (non-browser) BlackBerry application that talked to it in minutes. With Research In Motion's recent announcement of the end of life of MDS Runtime and associated development tools – developers need another option for building a (non-browser) rich client application that talks to web services. I'm sure there's a way to do it from a BlackBerry Widget but I still haven't had a chance to play with that technology yet.  The only other option is to consume the Web Service from a Java application and for my presentation this year at the View Domino Developer conference I built a Java version of the application I'd been demonstration for years using MDS Runtime.\nA few weeks ago I posted here that I was going to write some articles about how to build that application. From the responses I received, it seems that there are a lot of you who are interested in the information, so here we go…\nI'm going to split this topic into three parts:\n\nPart 1: (this article) How to build the Domino Web Service used in the sample application\nPart 2: How to create the Web Service Stub called by the Java application\nPart 3: How to build the Java application (for BlackBerry of course) that talks to the service\n\nBefore we begin, it's important to highlight that Research In Motion has published a lot of information about connecting to a Domino application from a BlackBerry device – be sure to check out na.blackberry.com/eng/developers/started/develop/ibm.jsp for additional information on the topic.\nLearning How to Build a Domino Web Service\nWhen I first set about learning about how to build Web Services in Domino, there really wasn't much information available. The first I'd heard about it was from some old articles that Gary Devendorf (now at Microsoft, go figure) on how to do web services in ND6 (that's Notes &amp; Domino 6 for the uninitiated). It was quite a mess; you had to build an agent that could read and write XML and had to hand craft the service's WSDL to use with some tools.\nWith the release of Domino 7, IBM made it much easier to build web services. Ultimately, the way I learned how to create the sample application in this article was from reading this: https://ibm.com/developerworks/lotus/library/nd7-webservices/. If you don't know how to do web services in Domino, that's a great place to start reading.\nAbout the Project\nWhen I first started looking for a good sample application for Domino developers I looked for something that would appeal to the widest audience of developer. I thought about how every Domino environment I'd ever worked with had at least one (sometimes more) additional contact databases outside of the standard Domino Directory. Since the BlackBerry already provided search capabilities against the Domino Directory, it seemed like a good idea to build a web service that would allow BlackBerry applications to lookup contacts in one of these other databases.\nAssuming that most of these additional contact databases were created against a copy of the Domino Directory, I built the web service using that template as a starting point. If you use this web service against a database that wasn't built off of that template, you will have to change the view, column and field names to match the needs of the target database.\nBuilding the Web Service\nThe web service is used to lookup contact information for a particular person in the database. It contains two operations: GetUserList and GetUserDetails. GetUserList takes as a parameter a portion of the last name being searched for and returns an array containing the names of all contacts who's last name begins with the specified string. GetUserDetails takes as a parameter the name of a contact and returns a UserInfo object containing several fields from the selected Contact document in the database.\nLet's get started building the web service. To do this, you will need to use Domino Designer 7 or higher – the screen shots in this article were taken in Domino Designer 8.5. The database you're creating will need to reside on a Domino server with the HTTP task enabled in order to be able to be accessed by the BlackBerry Java application we'll create in Part 3.\nOpen Domino Designer and open the contact database in design mode (it would be best to do this in a template, but that's up to ",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "RIM Announces Web Development Webinar",
  "date":"Thu Sep 03 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1252022400,
  "url":"/posts/2009/rim-announces-web-development-webinar/",
  "content":"On the RIM Developer Blog they just announced an  upcoming webinar called 'BlackBerry Developers Webinar: Web Development and Toolkits' Looks interesting; you can check it out here.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Started Playing with Google Docs",
  "date":"Wed Sep 02 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1251936000,
  "url":"/posts/2009/started-playing-with-google-docs/",
  "content":"I started playing with Google Docs the other day and I thought I'd share a little of my experience. I've been maintaining a long list of topics I want to write about here and it was filling up my task on my BlackBerry and desktop mail client. All of a sudden I had more personal tasks than work tasks and that's not good. I could maintain them in a word doc but then having access to the list from multiple places would be problematic. I use Second Copy to synchronize personal files between my laptop and desktop (which I'll write about in a few weeks), but I don't have many and it wasn't worth the effort to setup a new profile for just this one file.\nI thought I'd give Docs a try to see how it would work for me and I found it to be a really good fit. I quickly logged in and created a list of all of my topics. The editor has all of the features I need and I can work locally then save the document in the cloud when I'm on the network. I can then access (and update) the file from my personal desktop at home and my laptop while I'm on the road.  I lose the ability to have the list on my BlackBerry (I haven't accessed Docs from my device yet, I'm assuming it won't work - no Gears client until Device Software 5.0) but that's not important to me since the only time I use the BlackBerry for this is to quickly add a new item to the list which only seems to happen on airplanes. I'll just add the topic to my tasks list then copy it over to the document when I can. No biggie.\nI am seeing one interesting and annoying issue with the tool. I'm an expert Word user (sorry to brag) and use Headings to organize the structure of my documents and when you create a heading then enter a carriage return to begin the next line - for some bizarre reason Docs treats the heading and the first word that follows as the same word - and underlines it as a spelling error.\nPrinting is an interesting experience - when you print, Docs makes a PDF of the file on the fly and sends it to the browser. The browser opens Adobe Acrobat and lets you print, email, even mark-up the document. Pretty cool and a smooth feature.\nMy wife is going to help a friend create a resume tonight. I suggested Docs for this since my wife could help her create it then it would be accessible to both my wife and her friend. They can both work on it without needing to be in the same location. If it needs tweaking, my wife can make the updates and her friend could read it, email it or print it no matter where she is.\nAll in all, a good tool for me.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "myBlackBerry",
  "date":"Mon Aug 31 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1251763200,
  "url":"/posts/2009/myblackberry/",
  "content":"A few weeks back the press announced a new BlackBerry site managed by RIM called myblackberry.com. I quickly went online to see what it was and was frustrated for several weeks by its unavailability. Last week the pundits started announcing that the site was live so I went out again to try to access the site. Here's what I got:\n\nFigure 1\nI decided to try again today and was able to access then register with the site. Funny thing happened when I registered, it allowed me (actually required me) to set my own security question, but for some bizarre reason forced a minimum length for my answer. See below:\n\nFigure 2\nI dutifully entered my question and the answer but found that it was too short. What was I to do? I couldn't change my answer to fit the minimum length required by the form. Ridiculous. I had to pick a different question to use.\nI have to admit that I hate it when web developers force a requirement for an input field but don't tell me about it until after I populate the field wth the value I want to use. How much simpler would it be to tell me in advance what the requirements are so I could assess my security question and associated answer before hitting the submit button? I would have known immediately that my 'answer' was too short and selected a different question. Of course, after returning to the form you see above, certain of the fields I'd populated were blanked out, so I had to repopulate other portions of the form as well. Not a very helpful design.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "US Carriers Attitude Toward VOIP",
  "date":"Sun Aug 23 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1251072000,
  "url":"/posts/2009/us-carriers-attitude-toward-voip/",
  "content":"I'm continuously amazed at US Carriers attitude toward its customers. It's clear that everyday users just want to pay the carrier to use their network and be able to do whatever they want on it. The carriers of course don't want that - they want you to see them as providing specific services that you just can't do without and be willing to pay extra money for them. They're spending all of this money to add all these features when the majority of their users just want email, SMS, phone and web browsing. I don't know about you, but I don't use any additional feature provided by my carrier; I use the phone and my BlackBarry plan, nothing more.\nI was reading an interesting article on FierceWireless this morning about how all of a sudden Apple is 'still evaluating' the Google Voice application they blocked. What prompted this post was the following statement:\n'In its response, AT&amp;T said it had nothing to do with the situation.'\nApple's lengthy statement included a number of interesting tidbits. The company said &quot;There is a provision in Apple's agreement with AT&amp;T that obligates Apple not to include functionality in any Apple phone that enables a customer to use AT&amp;T's cellular network service to originate or terminate a VoIP session without obtaining AT&amp;T's permission.&quot;\nIn letters sent earlier this month to Apple and Google as well as iPhone operator partner AT&amp;T, the FCC asked why Apple chose to turn down Google Voice.'\nRead more: https://fiercewireless.com/story/apple-fcc-were-still-evaluating-google-voice-app/2009-08-21.\nThe carriers are so afraid of VOIP since it allows customers to just use their network - even for voice calls. All of that revenue from phone minutes that are never used would go away if I could do VOIP over my BlackBerry data plan.\nWhat most people don't realize is that for most of these so called VOIP solutions for BlackBerry the phone call is still made over the Voice network. It's not a VOIP call. When you place a call on Skype for BlackBerry and likely Google Voice, the application connects to a data center somewhere and tells it the user wants to make a call. The back-end application dials the BlackBerry device and, when the BlackBerry application accepts the call, dials the destination phone number and connects it to the BlackBerry. There's no VOIP here - the app is using the data network to initiate the call, but the actual call is executed on the carrier's voice network.\nThe other mind boggling aspect of this is UMA - a technology used by T-Mobile in the US to allow you to use a Wi-Fi network connection to place voice calls. Yep, it's VOIP, but get this - you have to pay the carrier to use it.  So, if you own a company and you have a Wi-Fi network, you can place calls over your own internal network, but your wireless carrier is going to charge you a monthly fee to use the feature. Huh? You're going to charge me to use my own network and equipment to place phone calls?  That's CRAZY!\nThe carriers are going to have to wake up and realize what their customers really want and stop blocking these technologies. If not, there's going to be a revolution. Some carrier is going to come around that's going to understand that they're just a pipe and make it easy for their customers. I'd gladly pay $100 a month to be able to do anything I wanted on the network - provided they stopped putting all sorts of junk applications on my device and stopped trying to get me to buy all sorts of extra services.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "RIM Purchases Torch Mobile",
  "date":"Sun Aug 23 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1251072000,
  "url":"/posts/2009/rim-purchases-torch-mobile/",
  "content":"Interesting that Torch Mobile announced today that they were purchased by RIM (and RIM didn't announce it).\nThere have been a lot of articles lately on the Web about how RIM's going to update the browser to match industry standards and I guess we now know. I'm curious to how this is going to work - I've always heard that WebKit was based on C, not sure how easy it's going to be to do a full port to Java so it will run on the BlackBerry. Only time will tell and I can't wait to see.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Notes Keyboard Shortcuts",
  "date":"Fri Aug 21 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1250899200,
  "url":"/posts/2009/notes-keyboard-shortcuts/",
  "content":"AS a follow-up to my BlackBerry keyboard shortcuts, I thought I'd share some Notes client keyboard shortcuts that I have always found helpful. As mentioned previously, I'm a keyboard guy – my hands are already hovering over the keyboard, why would I leave the keyboard to grab a mouse when I can get it done with what's at hand (sorry about the pun).\nThese shortcuts have been around forever, but so many people just don't seem to know about them.\nIn the Notes client, when you want to open a document in a view, just press the 'Enter' key and Notes will open it. You probably knew that one, but so many people will double-click on it as if they don't know there's another way.\nWhen you have a document open and you want to delete it, just press the 'delete' key – there's no need to return to the view to delete it. If there are documents in the view below the one you opened, Notes will mark the current document for deletion then open the next document in the view – nice, huh?\nIf you're reading a document in a view and you want to open the next document in the view, there's no need to close the current document then navigate to the next one – just press the 'Enter' key and Notes will close the current document then open the next.\nIf you're reading a document in a view and you want to open the previous document in the view, there's no need to close the current document then navigate to the previous one – just press the 'Backspace' key and Notes will close the current document then open the previous.\nImagine you're populating a database with a lot of new documents. You have a list of data in front of you and you have to add a separate document for every row in a spreadsheet. Perhaps it's a list of postal codes, product numbers or even office locations. There's a keyboard shortcut that will simplify the whole process and allow you to add those documents in no time.\nWhat you need to do is open the view and create the first document. While the new document is open for editing in Notes, press the three key Ctrl-Shift-Enter  combination (I always find it easy to press and hold the Ctrl key, then do the same with the Shift key and finally press the Enter key then release). Notes will save the current document, close it then create a new blank document using the same form used for the previous document (the one you saved using this keyboard shortcut).\nNice, right? This is my favorite Notes keyboard shortcut of all time. It's been in the client since Notes 2 and almost nobody knows about it. Try it out and let me know how much time you think this will save you the next time you need to populate a database by hand.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "BlackBerry Keyboard Shortcuts",
  "date":"Fri Aug 21 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1250899200,
  "url":"/posts/2009/blackberry-keyboard-shortcuts/",
  "content":"You probably already know this, but I thought I'd write about it anyway just in case. So many times people pick up a new piece of technology and focus so much on the hard things that they miss some of the cool easy things. For smartphones, all of them have special shortcuts that make day to day use of them less painful – but so many users just don't know about them.\nOn the BlackBerry smartphone, most business people spend the majority of their time in the email client write, reading, filing, forwarding and responding. Since it takes up so much of your time, let's make sure you're as efficient as possible. I'm a keyboard guy, so that's where a lot of this comes from. It's not that I don't like to use the trackball or a mouse, but when I'm on a computer or my BlackBerry, my hands (or my thumbs) are already hovering above the keyboard, so I just don't feel the need to move over (or up) to grab the mouse or trackball when I can just use the keyboard.  Here we go…\nWhen you open the BlackBerry 'Messages' application, the highlight is always on the current date. To create a new email message, merely press the enter key with the date selected and the BlackBerry will open a new message for you to start typing in. There's no need to click the menu button and select 'Compose Email.'\n\nTo open an email message, there's no need to click the trackball or use the menu to open a message, just select the message and press the 'Enter' key.\nWhen browsing messages in the Messages application, the following shortcuts are active:\n\n't': Go to the top of the message list\n'b': Go to the bottom of the message list\n'u': Go to the first (oldest) unread message\n'n': Go to the next date in the list\n'p': Go to the previous date in the list\n'space bar': To page down through the list of messages one screen at a time.\n'i': to file the selected message in a folder\n\nWith a message highlighted in the message list, you can delete the message by pressing the 'delete' key on the keyboard. There's no need to open the menu and select 'Delete' - that takes much longer.\nWhen reading a message, the same keys apply:\n\n't': Go to the top of the message\n'b': Go to the bottom of the message\n'u': Go to the first (oldest) unread message in the message list\n'n': Go to the next date message in the message list\n'p': Go to the previous date in the message list\n'space bar': To page down through the message one screen at a time\n'i': to file the message in a folder\n'delete': Delete the current message\n\nSo, when you've gotten off of a plane or left a meeting and you want to get caught up on your email, there's no need to open a message, close it and navigate to the next one. All you need to do is open the first message then press the 'u' button repeatedly until you've read all of the unread messages.\nI remember reading a comparison between BlackBerry and Windows Mobile and the reviewer complained about how 'hard' it was to press the 'alt' key to type a period at the end of every sentence. When typing any text on a BlackBerry, you can always press the space bar twice in succession to enter a period. When you press the key combination, the BlackBerry replaces the two spaces with a period and a space.  Makes it a lot easier, eh?\nThere are a lot more of them, you can find a good article (and a lot more shortcuts) at https://crackberry.com/blackberry-101-beginners-guide-keyboard-shortcuts.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "My Problem with PIN",
  "date":"Mon Aug 17 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1250553600,
  "url":"/posts/2009/my-problem-with-pin/",
  "content":"I've always gotten a big laugh when people don't pay attention to the acronyms they use.  Why do people say 'PIN Number?'  When you setup your ATM card, you assign a PIN to the account, a Personal Identification Number. So when you say 'PIN Number' what you're actually saying is 'Personal Identification Number Number.'  It just doesn't make sense. Why be redundant?\nThe next one of course is ATM Machine – we all know ATM stands for Automated Teller Machine but why then do people say 'ATM Machine?'  That's like saying 'Automated Teller Machine Machine.' There's even a McDonalds near me that has a sign hanging proudly in the driveway that says 'ATM Machine Inside.'\nI used to design networks and it's crazy when so many people say 'NIC Card.' NIC stands for Network Interface Card so when you say 'NIC Card' you're saying 'Network Interface Card Card' – it's redundant.\nI was in a car accident a while back, someone backed into me in a parking lot (I was too startled to use my horn, that would have saved me some aggravation – more on that one later). When I called the insurance company to make the claim, the claims representative said to me: 'What is the VIN number for your car?' I couldn't resist, I asked her – 'You have to know that VIN stands for Vehicle Identification Number, why would you say VIN Number (Vehicle Identification Number Number)?' She laughed and said that that's what people expect them to call it, so they ignore the fact that it's redundant and say it anyway.\nI had a customer who for the longest time would (probably still does) say 'DMZ Zone' when referring to a network's De-Militarized Zone. Of course I had to find a way to immediately use the term correctly to try to help him see how to use the acronym in a sentence but he never caught on: 'Yes, the server would be placed in the DMZ here.'  Too funny! What I never figured out is what does he think the 'Z' stands for in DMZ? Does he even understand what DMZ actually stands for?  I'll never know, I wouldn't risk the customer relationship by embarrassing him; perhaps I'll run into him some day and finally get around to asking him.\nOf course there's the BlackBerry Enterprise Server (The BES) – what I can't figure out is why do people feel the need to say 'BES Server'?  That's like saying 'BlackBerry Enterprise Server Server.' This one I know is a little nebulous since you may be trying to say something about the Server running BES and the phrase seems incomplete without the second 'server' like you're leaving out a word. Some people even take it a step further and spell it out: 'B. E. S.' - it's just a BES (pronounced like fez) nothing more. Now Research In Motion's Education Services folks are supposedly not allowed to call it a BES. For them, BES stands for BlackBerry Enterprise Solution. This is even funnier – so, your BES (solution) consists of a server running the BES (server) software. 'Yes, my BlackBerry Enterprise Solution implementation consists of a BlackBerry Enterprise Server running on this box…'\nOK, now finally back to the PIN.\nThis is a mystery that continues to befuddle me. Each BlackBerry device has a unique PIN associated with it. If you follow convention, it' makes sense that the PIN stands for 'Personal Identification Number' but that doesn't make sense. Why would a smartphone need a personal number?  I could see a mobile user needing a PIN, but why does a piece of hardware need a PIN?  I asked around when I worked at Research In Motion and nobody could tell me what it really stood for. I asked as many long term employees as I could find and even searched and searched the company intranet for the information, but nowhere could I find what PIN stands for.\nAs I started the book, I wanted to solve this mystery and write about it. I ended up not having the time to massage this topic into the book, so I decided to write about it here.\nWikipedia says the BlackBerry PIN is “an eight character hexadecimal unique identification number assigned to each BlackBerry device. PINs cannot be changed and are locked to each handset device. BlackBerry devices can message each other using the PIN directly or by using the Blackberry Messenger application.” You can find the reference and the rest of the text here: https://en.wikipedia.org/wiki/Blackberry_PIN#BlackBerry_PIN.\nI finally looked around on Research In Motion's web site and found my confirmation, it does stand for 'Personal Identification Number.' I still don't know why a smartphone needs a personal identifier, but it doesn't work as a 'Phone Identification Number' since the early BlackBerry devices (with PIN's) weren't phones, they were just wireless email devices. If you have more information, please use the 'contact me' link on the left to send me an email – I'll be happy to update the site.\nAnyway, to be consistent with the theme for this posting, when talking about the BlackBerry PIN, the last letter already stands for 'number', so don't you ever let me ever catch you saying 'PIN number",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Developer Blog",
  "date":"Mon Aug 10 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1249948800,
  "url":"/posts/2009/blackberry-developer-blog/",
  "content":"RIM just launched the BlackBerry Developer's Blog. I'm excited to see RIM writing developer oriented articles again - instead of stiff knowledge base articles, the blog should be written in a more conversational tone and will likely provide some interesting insights like RIM used to provide in the Developer Journal Articles (which no longer seem to be on RIM's web site).\nI'm going to be reading this one every day to see what end up there.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "End of Life for MDS Runtime Technology",
  "date":"Fri Aug 07 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1249689600,
  "url":"/posts/2009/end-of-life-for-mds-runtime-technology/",
  "content":"It's been rumored for some time now, but Research In Motion finally made the formal announcement this week. RIM announced an end of life of December 31, 2009 for BlackBerry MDS Runtime, BlackBerry MDS Studio and several versions of the BlackBerry Plug-in for Microsoft Visual Studio. See the announcement here:  https://na.blackberry.com/eng/developers/rapidappdev/eolnotice.jsp\nIt's really too bad. MDS Runtime applications were VERY easy to build and gave organizations an easy way to build Web Services clients for BlackBerry. When I worked for RIM, I worked with many customers who were running their businesses on MDS Runtime applications - every one of them will need to be rewritten in Java, the Browser or as a hybrid application using BlackBerry Widgets. there's noi hurry for organizations that are using older devices, but for newer devices, the MDS Runtime environment won't be available. Companies will have to decide which is more important - new devices or the ability to run MDS Runtime applications.\nAs promised last week, I'll soon write an article that shows how to build a BlackBerry Java application that talks to a Web Service - I have a feeling that many of you will need this information very soon.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry App World Alert",
  "date":"Wed Aug 05 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1249516800,
  "url":"/posts/2009/blackberry-app-world-alert/",
  "content":"I upgraded the BlackBerry App World Client on by BlackBerry yesterday and today I noticed a new alert on my device Home Screen. I had to look at it for a while to figure out what it was, but the alert icon turns out to be a notification for an application update in the BlackBerry App World. Here's a screen shot of the alert:\n\nWhen you open the App World application and open the list of installed applications, you'll see that there's an asterisk on the applications that have an update available. In this case, my free CBS news application has been updated.\n\nThe notification also appears in the Messages application which is not something I expected. What's really cool is when you open the message, it automatically launches the App World application so you can perform the specified upgrade. I'm trying to find out more about this ability - RIM suggested I add the topic to the book, but I didn't have time to add it. As soon as I learn more, I'll write an article about it and post it to this site.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Profile Mystery",
  "date":"Mon Aug 03 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1249344000,
  "url":"/posts/2009/blackberry-profile-mystery/",
  "content":"For years I've wondered about something and I've not been able to get an answer from any of my former colleagues at RIM. When you open the Alerts application and edit a profile, you'll see the highlighted entry as one of the options for defining and alert. You'll see all of your messages clients (Desktop for the BES email and up to 10 other email accounts through BIS) listed so you can specify settings for each email account but at the bottom of the list is always the one shown below: Web Client. What is this Web Client? I haven't been able to figure it out and a search didn't reveal anything. At Lotusphere this year, I asked everyone from RIM I saw there and got no answer.  Help? What's it for?\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "OK, if you really want to talk about old computer manuals...",
  "date":"Wed Jul 29 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1248912000,
  "url":"/posts/2009/ok-if-you-really-want-to-talk-about-old-computer-manuals/",
  "content":"I'd forgotten something even older than the MS-DOS books I posted about yesterday. Remember this? Also in my collection (I have two of them)\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "Information Week Mobile Alerts",
  "date":"Tue Jul 28 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1248825600,
  "url":"/posts/2009/information-week-mobile-alerts/",
  "content":"I made the mistake a few months ago of signing up for mobile alerts from Information Week. I thought I was signing up for email alerts and wasn't paying attention when they asked for my phone number.  Turns out they're SMS alerts. What IT related news could be important enough that I would need to be sent an SMS alert?  Just send me an email. it just doesn't make sense.\nI went back in and tried repeatedly to find some way to cancel the alert but the company managing the site has links for subscribing to the service but absolutely nothing about how to unsubscribe. so, I waited patiently for the first alert thinking there might be a way to reply and unsubscribe. Nope, nothing. So after a couple of months of getting these SMS messages I really didn't care about I finally contacted the editors of the magazine for help (I didn't have any other recourse, there was nothing on their site that led me to believe I could get help from anyone else). The editor responded immediately, apologized for the trouble and promised to get it taken care of.  No change - I'm still getting alerts. Every time I do, I send an email to the editor and he promises to fix the problem (over and over again). Don't get me wrong, I don't think he's not trying to help me - I just think that the company they've outsourced this 'feature' to is clueless and just not being responsive.\nI hope someday they finally figure this out and remove me from their mailing list. The issue I have is that SMS messages cost my employer money and I can't have that.\nUPDATE: They appear to have finally removed me from the mailing list. Only time will tell.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "DOS Developer BooksGuides",
  "date":"Tue Jul 28 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1248825600,
  "url":"/posts/2009/dos-developer-booksguides/",
  "content":"Periodically I spend some time cleaning out some old books from my technical book shelf (I never throw out fiction and non-fiction books) that I no longer use. As I moved some books around on the shelf, I noticed some very old (late 80's, early 90's) MS-DOS books on the shelf. Think it's finally time to get rid of them?  I haven't done any DOS machine programming since 1995 probably.\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "RIM Introduces New BlackBerry Tools for Web Developers",
  "date":"Mon Jul 27 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1248739200,
  "url":"/posts/2009/rim-introduces-new-blackberry-tools-for-web-developers/",
  "content":"RIM formally announced the new BlackBerry Tools for Web Developers. These tools had been in beta for a while and I got a chance to work with them while writing the book chapter around debugging web applications. The tools are a plug-in for Eclipse and another for Microsoft Visual Studio. They basically allow a web developer to build web applications (static or dynamic) and debug them on BlackBerry devices directly from within the IDE. The cool thing about them is that the debugger from either IDE connects to the device simulator through the debugger and allows developers to step through dynamic code (JavaScript, AJAX code using XMLHTTPRequest and more) while it runs in the simulator. If needed, it can also do the same thing directly through an USB-connection to a physical device. Way cool.\nThe thing I liked the most was the window that could be used to watch all traffic between the device and web server using XMLHTTPRequest. If I was building an AJAX application (I refuse to treat it as a word, it's an acronym), I'd need this tool to make debugging and troubleshooting as simple as possible.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Learning Drupal",
  "date":"Thu Jul 23 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1248393600,
  "url":"/posts/2009/learning-drupal/",
  "content":"I had an idea for a new web property (I'm not saying what yet) and thought it would be something cool to create using a different Content Management System(CMS) than Joomla (the CMS I'm using for all of my other sites). I selected Drupal because it was another CMS FatCow installed for free but also because of what many people have said about it online. It's interesting; Drupal is more configurable and more flexible than Joomla - more targeted at developers. It has less modules, but much much more flexibility in how it's configured and how data renders. I'll start working more on the site in a few months and we'll see what happens.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "BlackBerry Device Wipe in Switch Device Wizard",
  "date":"Thu Jul 23 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1248393600,
  "url":"/posts/2009/blackberry-device-wipe-in-switch-device-wizard/",
  "content":"In the more recent versions of the BlackBerry Desktop Manager (DM) they added an automatic update feature which I just saw work for the first time last week. My 4.7 DM prompted me then automatically upgraded to DM 5.0. I decided this week to switch back to my BlackBerry 8900 from my BlackBerry Bold 9000 and noticed something interesting as the device switch wizard completed - it had copied everything from my old device to the new one then the program asked if I wanted to reconnect my old device and wipe it. Nice!\nIt's not a feature I'll ever use because you have to make sure everything is working on the new device before you wipe the old one, but less experienced users will like how complete the process is now.\nI had a lot of issues completing the device switch, it kept failing without telling me anything about why it failed. I finally googled the error message and wiped the new device and it worked like a champ. It's amazing though that a process will fail and the software doesn't provide any information at all about what caused it. It's hard to troubleshoot a problem when you have absolutely nothing about what the problem was.  So apparently this new DM still needs some work.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Pizza Box Speaker Phone",
  "date":"Thu Jul 16 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1247788800,
  "url":"/posts/2009/pizza-box-speaker-phone/",
  "content":"I was out of town with a colleague a few years ago and we needed to participate in a call with a customer or some others on our team (I can't remember which). We didn't have a meeting room to use, so we decided to do the call from Randy's hotel room. He had eaten Pizza the night before and had an empty pizza box in his room.\nWhen the call began, he dialed in with his BlackBerry and turned on the speaker phone so we could both hear. After a few minutes of holding the phone, he got tired of holding it and placed the phone (with the speakerphone turned on) on the empty pizza box. As soon as he did, the sound emanating from the phone became much clearer and easier to hear. The phone we were using was an 8700c and it had a speaker port on the back of the phone. When sitting on the empty box, the speakerphone resonated with the box and amplified the sound coming from the speakerphone. What we got then was a better, clearer listening experience.\nIt was a great, free and easy way to enhance the speaker phone. Try it some day when you have an empty box lying around. Pizza's probably the best since it has a large enough surface area and thin enough depth that it works beautifully.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Selected as a Speaker for the Midwest Lotus User Group Conference 2009",
  "date":"Wed Jul 15 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1247702400,
  "url":"/posts/2009/selected-as-a-speaker-for-the-midwest-lotus-user-group-conference-2009/",
  "content":"I found out last night that BoxTone (and I) had been selected to be a speaker (for two sessions) for the Midwest Lotus User Group Conference 2009 in Chicago at the end of August. I'll be speaking on two topics:\n\nPreparing for the Mobile Applications Onslaught\nPrepping for BlackBerry Enterprise Server v5: A Lotus Domino Upgrade Unlike Any Other\n\nThe mobile applications presentation I've given several times. I gave it at two of BoxTone's Mobile Professional Network meetings in NY and Atlanta.I also presented the topic at the View Domino Admin conference in Boston in April. It's a high energy discussion of why BlackBerry &amp; system administrators fear mobile apps, what the real concerns should be and how to mitigate them.\nThe second topic is intended to help BlackBerry/Domino Administrators understand how to prepare their environments for the upgrade to BES 5.0 - which won't be too hard, but there's work that will need to be done.\nAnyway, I'm excited about the event and I love to present technical topics. Please stop by and see me at the event if you attend.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Let me Google that for you",
  "date":"Tue Jul 14 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1247616000,
  "url":"/posts/2009/let-me-google-that-for-you/",
  "content":"One of my colleague's pointed me to this site a few months ago, for people who constantly ask you questions that could be easily answered on Google.  It's called Let me Google that for you and it can be used to create a link that when opened demonstrates how to do the specific search in Google.  Not subtle.\nIf you want to search on Twitter for example, you would grab the following url from the site: https://lmgtfy.com/?q=twitter and it would then show you how to do the search then display the results for you automatically. Too funny. I used it on my cousin Jennifer, she wasn't amused.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "What is it with Ruby books",
  "date":"Thu Jul 09 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1247184000,
  "url":"/posts/2009/what-is-it-with-ruby-books/",
  "content":"I work for a company (BoxTone) that has a web-based enterprise software product using Rails. Being a product manager, I wanted to know more about the technologies being used to create the product I'm responsible for managing - makes sense, right?  So I set out looking for a book to read on Ruby then later I'll dig into Rails.  Being a huge fan of O'Reilly books (even though they passed on my BlackBerry book) I purchased a copy of Ruby by Example: Concepts and Code and started reading it.\nHated it.\nI've been a professional software developer for more than 20 years now and I thought I could leverage that experience and just pick up rails by example. The book's examples were so obtuse and the descriptions of the code so incomplete that I spent a lot of time scratching my head, trying to figure out what the sample code was actually doing. Not a good thing for a 'by example' book.\nSo, I set that book aside and started reading Learning Ruby (also from O'Reilly). It's a better book in that it's fast hitting, short code samples and a direct explanation of every topic as it's presented. My problem with the book is that the many of the code examples actually make it harder to understand the topic being discussed.  When discussing Regular Expressions, the book gives repeated examples that all have the same result! It's crazy. When learning RegEx, I don't want to see example after example of a RegEx applied to a two line string return the first line of the string over and over and over again. What I want to see is a big string and how I can use RegExes to pull out part of it in several ways.  It just makes it harder to learn when you see the same result of an expression repeatedly.\nAnyway, after reading hundreds of computer books in my life, why are Ruby books so poor?  \nThe final straws for me were twofold.\nAn example of how to use  the .reverse method to reverse the order of characters in a string. One of the examples the author gave was to use this method to reverse the order of a palindrome! How is that a good example of how to use a method? &quot;OK, I'm going to show you how to reverse the order of characters of a string comprised of characters that spell the same thing forward and backwards.&quot; Huh? How do you even tell the difference between before and after? What's the point? Wow!\nLater on, there is a discussion of using .ljust and .rjust to left and right justify strings. Right in the middle of the discussion, the author says:\n&quot;Still confused? So am I, but we'll go on&quot;\nHuh?  Seriously? Is that how the author feels about me? &quot;ya, I know you're confused, so am I, let's ignore it and move on.&quot; Uh, that doesn't help me learn how things work. It's weird that he spends so much time discussing something that's pretty easy to understand anyway then tells us he's confused? No, not what I expect.\nRuby is a little different and it's a cool language, but I just don't understand why the two leading books on the topic I picked up by a very respectable publisher are so bad.  Please don't get me wrong, I'm not trying to bash O'Reilly, I have almost 40 of their books in my library, it must just be ruby authors.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Miscellaneous"
  
  ]
  },

  {
  "title": "New BlackBerry Developers",
  "date":"Tue Jun 30 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1246406400,
  "url":"/posts/2009/new-blackberry-developers/",
  "content":"My wife pointed me to a BlackBerry Forums post this morning from a developer looking for information on how to get started with BlackBerry Development. The responses were that no good books existed and that all you needed was access to the BlackBerry Developer's web site and the JavaDocs for the Java development tools. I happen to not agree. While RIM has a lot of great information on their web site, most of it was written from the standpoint that you kinda already know what you're doing. There is some development 101 stuff there, but there's no place to find everything there is to know about how to build BlackBerry applications.\nThat's why I wrote the book.\nOne of the forum members had posted a link to a list of (very useful) links for a BlackBerry Developer, but they focused on Java Development. when I replied with information about my book, he responded with:\n\n&quot;IMHO this information is far more better than any existing book on bb development. Long time ago when I started with BB development I had only JDE samples at hands. And it (with RIM API javadocs) was more than enough to study this technology.&quot;\n\nand simply repeated the link to his list of topics. I have two issues with this:\n\nThere aren't any existing BlackBerry Development Books\nEveryone assumes that to start working with BlackBerry Development means beginning with Java\n\nThere is still a whole ton of ancillary information that must be understood before you can really understand BlackBerry Development. If you take a look at the book, (it's not published yet, so this number may be off) there is about 300 pages of detailed content before even beginning to talk about Java development and the BlackBerry Java Development Tools. The Java documentation doesn't explain: \n\nWhat the different paths a request can take to a server (WAP, BIS-B, Direct TCP, MDS, Wi-fi)\nWhat MDS is and what it does to provide secure access to internal resources and optimize data communication to the device\nWhat Application Data Push is and what all the available options are\nWhat some of the unique features of the BlackBerry Browser\nHow to debug web applications\nHow to use the different Java development tools\nHow to deploy Java applications\nHow to use the MDS Simulator and the BlackBerry device simulators\n\nand a whole bunch more. You can't just stare at the sample code or the JavaDocs and understand BlackBerry Development. You need more - and that's just what my book provides.\nCheck it out when you get a chance: bbdevfundamentals.com.\nSorry about  the advertisement.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "BlackBerry Java Tools Build Rules",
  "date":"Sun Jun 21 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1245628800,
  "url":"/posts/2009/blackberry-java-tools-build-rules/",
  "content":"While writing book chapters  on the BlackBerry Java Development Environment (JDE) and the BlackBerry JDE Plug-in for Eclipse (eJDE) I came across a feature that just wasn't documented anywhere. Both tools support definition of 'Build Rules' but the online help, the knowledge base and the internet as a whole doesn't have anything about them. RIM was kind enough to explain it to me:\nA build rule is a command string which is executed even before the &quot;Pre-build&quot; command. It can be any command which can be executed in the DOS console. Developers usually use it to manipulate files:\n\nA developer can define multiple build rules.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Killing BlackBerry Device Simulator in the eJDE",
  "date":"Sat Jun 13 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1244937600,
  "url":"/posts/2009/killing-blackberry-device-simulator-in-the-ejde/",
  "content":"I learned something interesting this evening regarding killing the BlackBerry Device Simulator on Windows Vista 64-bit. As I reported previously, you can't close the simulator on 64-bit Vista without resorting to the Task Manager. In writing the chapter of my book on the BlackBerry JDE Plug-in for Eclipse I accidentally discovered that if you 'disconnect' Eclipse from the simulator (by clicking on the 'Disconnect' button in the Debug Perspective), it closes the simulator as expected.  \nNice, eh?\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Grammar Checking Source Files",
  "date":"Fri Jun 12 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1244851200,
  "url":"/posts/2009/grammar-checking-source-files/",
  "content":"I'm working on the chapter of the book that deals with the BlackBerry JDE Plug-in for Eclipse (eJDE) and I had just completed importing the Samples workspace (RIM doesn't ship it as an Eclipse workspace with the eJDE, so you have to import it manually into an existing workspace) and noticed something funny. In the comments for the HelloWorld sample application, the comments included:\n\nI think he or she meant 'seminal' but it stuck me as interesting that nobody ever things to grammar check comments in sample applications. Eclipse will spell check comments (which is sometimes annoying) but I never thought grammar checking was important until I saw that sample.\nIt had me LOL.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Joomla is Amazing",
  "date":"Thu Jun 04 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1244160000,
  "url":"/posts/2009/joomla-is-amazing/",
  "content":"Joomla! is absolutely amazing. I discovered this open source Content Management System a month or so ago when looking at the free tools my ISP (FatCow) provides. I setup one site and very quickly had Joomla running almost every one of my sites (the only one that isn't Joomla yet is my McNelly SoftWorks site. I purchased a book on the technology (as soon as you try to add a menu item in Joomla you will know why I had to purchase a book to learn how to use this thing).\nAnyway, the reason for this post is because every so often I take a few minutes and look for plug-ins to use to enhance the site. Yesterday, 20 minutes or so had me up and running on a code citation plug-in used on this site to highlight source code. This morning, I decided I needed a way to allow visitors to post articles to Facebook and other social networking sites. In about 15 minutes, I'd downloaded, installed and tested two different free extensions before selecting the one you see in the menu on the left.\nThere's thousands of extensions available and this site and others I manage are full of them. I'm using Joomla Extensions for code display, attachment management, guest books, Google and Amazon ads, Google Analytics, Captcha and more. The only one I'm looking for and can't seem to find (yet) is an extension that will let people sign up for notifications whenever there's new content on the site. I posted a question about this on the Joomla Forums and nobody has responded yet. Maybe I'll write one.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "Content Management Systems"
  
  ]
  },

  {
  "title": "DeviceInfo.isInHolster()",
  "date":"Sun May 17 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1242604800,
  "url":"/posts/2009/deviceinfo.isinholster/",
  "content":"I'm working on a BlackBerry Java application that uses the DeviceInfo class to determine information about the device the application is running on. The original version of the program I wrote used DeviceInfo.isInHolster() to determine whether the device is in the holster or not, but the documentation says that method has been deprecated. The problem is that it doesn't say what to use in its place (actually, I finally noticed the 'Deprecated' link at the top of the JavaDocs that listed the objects, methods and fields that had been deprecated but that's not the point of this story).\nIt turns out that the method has been implemented (of sorts) in net.rim.device.api.system.Sensor. Unfortunately, instead of returning a simple Boolean True or False, it has been implemented through a call to:\n\nWhich returns an integer value.I struggled with this because I'm just not a day to day Java developer. What I missed in the docs was that it returns an integer and the possible states are Sensor.STATE_IN_HOLSTER and Sensor.STATE_OUT_OF_HOLSTER. Here's what it said:\n\nAnyway, I finally figured it out this morning with some help from Sanyu from RIM. Here's an application that uses a SensorListener to determine sensor state:\n\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Debugging BlackBerry Applications on Vista 64-Bit",
  "date":"Sat May 16 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1242518400,
  "url":"/posts/2009/debugging-blackberry-applications-on-vista-64-bit/",
  "content":"I'm knee deep in my book on BlackBerry development BlackBerry Development Fundamentals and I'm running into a rather annoying problem. The machine I'm doing most of my writing on is running Microsoft Vista 64-bit and while the BlackBerry device simulators run on Vista, they won't close when run on a 64-bit version of Vista. RIM is aware of the problem, but the Java development environment and the Visual Studio tools I'm working with both require that you close the simulator before you can go back in and edit the source code. Very annoying, I hope they fix that problem soon.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Interesting BES 5.0 Upgrade  Fact",
  "date":"Tue May 12 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1242172800,
  "url":"/posts/2009/interesting-bes-5.0-upgrade-fact/",
  "content":"Learned something interesting about the BES 5.0 upgrade. When you upgrade an existing BES domain, Administrator accounts and Roles are deleted. What this means then is that a large organization upgrading a BES 4.1.x BES to 5.0 will have to quickly re-add the Administrator accounts and roles so other Administrators will be able to continue to be able to manage the environment.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  },

  {
  "title": "Lotus Notes Local Encryption Gotcha",
  "date":"Mon May 11 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1242086400,
  "url":"/posts/2009/lotus-notes-local-encryption-gotcha/",
  "content":"I presented at a Domino Developer's conference in Boston a few weeks ago and provided a sample application that I used in my session. Unfortunately I forgot that in Notes 8 (might have started in Notes 7, I don't remember) local encryption is turned on by default.  I got an email from a participant last week telling me he couldn't access the database so I had to create a new copy without local encryption and send it to him and to the conference. How silly.\n I had to contact the conference people and get them a copy. If you attended the session and have the encrypted database on the conference CD, just contact the conference people or me (using the email address in the presentation) and you'll get a new copy.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "IBM Lotus Domino"
  
  ]
  },

  {
  "title": "Broken Display & 507 Error",
  "date":"Sun May 10 2009 20:00:00 GMT-0400 (Eastern Daylight Time)",
  "date_timestamp": 1242000000,
  "url":"/posts/2009/broken-display-507-error/",
  "content":"I broke the screen on my BlackBerry Bold 9000 Smartphone yesterday. While switching to an 8830 I had in a drawer, I encountered a 507 error while switching from one device to another. After much trial and error, I discovered that I had to pull the battery, connect the device to the BlackBerry Desktop Manager and reload the device software. The problem was that it would get so far and give me a 507 error again. What I ultimately had to do is start the process again and put the battery in right when it finished the software load and resets the device.\nApparently you can't have a battery in to reload from scratch, but you do have to have a battery in to restart after the load.\n",
  "tags":[
  
    "post",
  
    "post"
  
  ],
  "categories":[
  
    "BlackBerry"
  
  ]
  }

]