tag:blogger.com,1999:blog-30043946668623341392024-03-05T15:54:47.271+01:00ThisIsWhyTheInternetExistsor: My take on development and tech stuffsFelix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-3004394666862334139.post-51876794974111743922022-08-01T14:47:00.003+02:002022-08-01T17:19:14.455+02:00I purchased a Japanese Sony Clie PEG-UX50: can I turn it into an English device?<p>If you've known me for a certain amount of time, sooner or later the subject of my fascination for the Palm OS ecosystem might have come up. For the people who are unfamiliar with this particular fascination, a little backstory. </p><h2 style="text-align: left;">How did my fascination with Palm OS begin?</h2><p>When I was about 13 years old it was apparent that I had some issues organising certain things in my life (such as: homework, showing up at violin lessons on time, time keeping in general). I'm not sure how, but at some point my love for Tech led me to a solution: I could get a second hand Palm OS PDA to help me! I'd just put every appointment and deadline in this thing, and it would remind me whenever I'd need to do something. </p><p>This first device was a Sony Clie 4.x device (the PEG-N760C), and after that I upgraded to a Clie NR70, a Tungsten T2, Tungsten T3 and finally the LifeDrive. From the devices listed here I sold the Clie's, broke the T2 and I still have the T3 & LifeDrive. </p><p>However, now that phones were getting smarter and smarter my need for a PalmOS PDA as a daily driver decreased. Feature phones could sync with Google Calendar and even Email and RSS clients were prevalent in most feature phones in the era of 3G connectivity. Once I upgraded from a Sony Ericsson W850i to the W960i (which ran Symbian) I ditched the PalmOS devices altogether. </p><h2 style="text-align: left;">I do not speak Japanese</h2><div>These days I am used to being able to reboot a device into a <a href="https://en.wikipedia.org/wiki/USB#Device_Firmware_Upgrade_mechanism" rel="nofollow" target="_blank">DFU</a> or <a href="https://source.android.com/setup/build/running" rel="nofollow" target="_blank">Fastboot</a>/Bootloader mode where I can supply a ROM file or update to change the firmware of a device. We see this in the RP2040, Android phones, 4G USB dongles, hardware wallets, fitness trackers. When I purchased a Sony Clie PEG-UX50 on Sendico I somehow forgot about the fact that at the time firmware updates were nowhere as available as they are today. Oh, and the fact that Palm OS devices had different ROMS based on the region where it was used. If you purchased your device in Japan, you only have Japanese applications inst<br />alled and nothing else to choose from. Which I did. And I don't speak (or read) Japanese.</div><div><br /></div><div>The issue here is that if a device hasn't received a firmware update from the manufacturer in it's lifecycle, you'll have to resort to reverse engineering the protocol using 0 resources. Because at the time manufacturers didn't really follow a reference protocol for these things. In some cases you send some magic bytes over serial, and everything you send afterwards is directly written to the flash chip. In other cases a protocol has been used for several generations of devices from the same manufacturer. Sometimes a Windows updating app was released to end users, sometimes a .prc file patched ROM files (so the update changes only live in RAM. If you fully deplete your battery, your device returns to its unpatched state). </div><div><br /></div><h2 style="text-align: left;">A compromise: Install PRC files to RAM</h2><div><a href="https://dmitry.gr/" rel="nofollow" target="_blank">Dmitry Grinberg</a> is one of the Palm OS heroes. Their fascination with the OS has led to software that was amazing when Palm OS was "alive", but grew even more when it died. Nowadays Dmitry is working on making Palm OS 5.x work on Palm OS 4.x devices by use of a SDIO/Memory Stick containing an ARM CPU, this project is called <a href="https://dmitry.gr/?r=05.Projects&proj=27.%20rePalm" rel="nofollow" target="_blank">rePalm</a>. It's worth a read if you're curious. </div><div><br /></div><div>However in the process of discovering what makes a Palm OS ROM tick Dmitry came up with this concept of '<a href="https://palmdb.net/app/palm-roms-split" rel="nofollow" target="_blank">split ROMS</a>', a format that allows him to decompose a ROM dump into files, while maintaining the ability to assemble back to a valid ROM again. Luckily he had a split rom for the en_US UX50, so I could extract the zip and install the PRC files to see which ones break, and which ones don't.</div><div><br /></div><h2 style="text-align: left;">Preliminary findings</h2><div style="text-align: left;">Installing <span style="font-family: courier;">general.prc</span> from the split ROM causes the system to fail during a soft reset. However, installing the following files translates most of the preferences:</div><div style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj-9NdtipDYnGOe8DMhHE52cCh44V6iM5io1tf1NIs3hM6zJcZSA4bx9aEK8riOBmrxzosz1oAb54HBi6Td5vcNr0aDHFzGA-jpfKMCux8N1RhVdke3Ol5VQpuHgw8_1ZAtAO_flgvojEcuA-pbHlfLuiUhYgBfcfh7e9JXCT7y-0ycaZ_J8VFRTTQlHA" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="" data-original-height="3840" data-original-width="5120" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEj-9NdtipDYnGOe8DMhHE52cCh44V6iM5io1tf1NIs3hM6zJcZSA4bx9aEK8riOBmrxzosz1oAb54HBi6Td5vcNr0aDHFzGA-jpfKMCux8N1RhVdke3Ol5VQpuHgw8_1ZAtAO_flgvojEcuA-pbHlfLuiUhYgBfcfh7e9JXCT7y-0ycaZ_J8VFRTTQlHA" width="320" /></a></div><ul style="text-align: left;"><li><span style="font-family: courier;">BluetoothPnl.prc</span></li><li><span style="font-family: courier;">Buttons.prc</span></li><li><span style="font-family: courier;">Date & Time_enUS.prc</span></li><li><span style="font-family: courier;">Digitizer_enUS.prc</span></li><li><span style="font-family: courier;">Formats_enUS.prc</span></li><li><span style="font-family: courier;">General_enUS.prc</span></li><li><span style="font-family: courier;">Network_enUS.prc</span></li><li><span style="font-family: courier;">Owner_enUS.prc</span></li><li><span style="font-family: courier;">Phone_enUS.prc</span></li><li><span style="font-family: courier;">Preferences_enUS.prc</span></li><li><span style="font-family: courier;">Security_enUS.prc</span></li><li><span style="font-family: courier;">ShortCuts_enUS.prc</span></li><li><span style="font-family: courier;">SpecialSetupPnl.prc</span></li></ul><div>Note: any file that has a _enUS postfix will have to be copied to internal memory first (I used <a href="https://palmdb.net/app/filez" rel="nofollow" target="_blank">FileZ</a> to do this), and then renamed (to _jpJP) using <a href="https://www.ppcompiler.org/download.php?lng=fr" rel="nofollow" target="_blank">Bird</a> (or something similar). This allows the native applications to load the text strings as if they were the "native" translations for the app. It looks like the actual application code is the same for most of these "preference"applications. </div><div><br /></div><div>Other applications that can be installed from the split ROM:</div><div><ul style="text-align: left;"><li>I don't have a detailed description for these, I installed all four of these and my Grafitti panel stopped showing the Japanese characters, so I was happy. But you might need only one of these files to achieve that. </li><ul><li><span style="font-family: courier;">StatusBar.prc</span></li><li><span style="font-family: courier;">StatusBarSkin.prc</span></li><li><span style="font-family: courier;">StdInput.prc</span></li><li><span style="font-family: courier;">StdInSoftGSkin.prc </span></li></ul><li><span style="font-family: courier;">LauncherCW.prc</span> - This is the Clie 3D launcher</li><ul><li>I recommend installing CLIELauncherDefaultList.prc as well, this way you can reset some of the japanese app descriptions to their english counterparts easily. </li></ul><li><span style="font-family: courier;">CardInfo_enUS.prc</span></li><li><span style="font-family: courier;">Calculator_enUS.prc</span></li><li><span style="font-family: courier;">HotSync_enUS.prc</span></li><li><span style="font-family: courier;">Address Book.prc</span></li><li><span style="font-family: courier;">Address Sort Library.prc</span></li><li><span style="font-family: courier;">AudioPlayer.prc</span></li><li><span style="font-family: courier;">CLIEFiles.prc</span></li><li><span style="font-family: courier;">CLIECamera.prc</span></li><li><span style="font-family: courier;">CLIEAlbum.prc</span></li><ul><li><span style="font-family: courier;">ClieAlbumDbMgr.prc</span></li><li><span style="font-family: courier;">CLIEAlbum_GroupDB.prc</span></li><li><span style="font-family: courier;">CLIEAlbum_TemplateDB.prc</span></li></ul><li><span style="font-family: courier;">CLIEMemo</span></li></ul><div>Files to avoid touching:</div></div><div><ul style="text-align: left;"><li><span style="font-family: courier;">DAL.prc</span></li><li><span style="font-family: courier;">General.prc</span></li><li><span style="font-family: courier;">Boot.prc</span></li></ul><h2 style="text-align: left;">Conclusion</h2></div><div>So: it might be hard to impossible to achieve a cross-region ROM flash for these devices because the manufacturer never released any ROM updates, so the update mechanism would have to be reverse engineered, which likely means sacrificing devices in the process. </div><div><br /></div><div>However, by using split rom archives, we can install translation files of most of the preferences to the device RAM and change their identifier (from _enUS to _jpJP) so that the system thinks they should use these translation files instead of the ones in ROM. This allows us to use the device (mostly) as if it were an English device. The translation files are ususally small and it shouldn't be a huge sacrifice to have these installed in RAM for most people. </div><div><br /></div><div>Some of the CLIE apps include their text strings in the app itself. This means that the entire app needs to be installed in RAM. Whether this is worth it is up to the user. But CLIE Album is a few hundred KB, so it might not be worth it if you never use that particular app. </div><div><br /></div><div>If I make any significant future discoveries I'll share them here. Hopefully sharing this knowledge has been useful to others. If it was, please let me know by leaving a comment. </div></div>Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-72701095516405216642022-05-01T12:53:00.006+02:002022-05-01T13:21:05.764+02:00The user-hostile design of the SumUp 3G (+ teardown)<p></p><div class="separator" style="clear: both; text-align: center;"><br /></div>About a month ago a company (<a href="https://nl.reviewclub.com/nl" rel="nofollow" target="_blank">reviewclub</a>) gave me the opportunity to test the SumUp 3G+ payment kit. Reviewclub allows people to review a product for 4 weeks in exchange for giving your honest opinion about a product after a few weeks of use and placing that opinion on the website of an online retailer. <p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjnp4D8pXgT4rS6huWsaY9_d8h2wNg19qo_zlR_gLIjn_TAvDCNQvuLpG8eXmQv85I7baqKc6CZsInr___T1W-obtShfqfAm5qP4CVfnb9RPlXU2g0rCzxC9sZvyjBTx3biIL5gNIsI5o3a-tYY3X4jBZSeQow9qyKz_g2UT7MJ6ZtLzB8_B0-4j18oww" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="" data-original-height="1382" data-original-width="1536" height="153" src="https://blogger.googleusercontent.com/img/a/AVvXsEjnp4D8pXgT4rS6huWsaY9_d8h2wNg19qo_zlR_gLIjn_TAvDCNQvuLpG8eXmQv85I7baqKc6CZsInr___T1W-obtShfqfAm5qP4CVfnb9RPlXU2g0rCzxC9sZvyjBTx3biIL5gNIsI5o3a-tYY3X4jBZSeQow9qyKz_g2UT7MJ6ZtLzB8_B0-4j18oww=w170-h153" width="170" /></a></div>At the end of the test the user is often given the opportunity to purchase the product at a discount, or send it back using a prepaid shipping label. I have purchased this device, and since it was now my property I was very curious to know what cellular operator was being used in these devices. So within 24 hours after purchasing this device I've rendered it useless with my curiosity and I'd like to prevent others from doing the same. Oh, and for the curious ones: the SIM card used in my device was from Soracom.<p></p><p></p><h3 style="text-align: left;">Initial impressions</h3><div>The <a href="https://sumup.nl/3g-pinapparaat/" rel="nofollow" target="_blank">SumUp 3G</a> is a pretty nifty device for people who don't process many payments and don't have a lot of requirements in terms of printing detailed receipts (with individual products on it) quickly. The purchase price is relatively low, and there are no monthly costs. Despite the low monthly cost they do include a sim card with a data plan, which allows the user to receive payments in any location where at least any of WiFi/4G/Bluetooth (via phone) connectivity are available. </div><div><br /></div><div>The device had it's quirks (the payment terminal didn't always snugly fit in the printer dock, charging didn't always work, sometimes if a few apple pay payments were done in a row the device would say "insert card" which obviously is impossible if the card is a phone). But given the target audience I'd be able to forgive this since the barrier to get started with payment is pretty low. However there is one HUGE issue:</div><div><br /></div><h3 style="text-align: left;">User hostile design</h3><div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg9dUs7LPJ9gQWekesHZv__yrBEEZWf0DwhFkz9u-EE9s_51hICFWbbQzuwSPFSA6-IUQigUCwcKw9LfAjncxKySEg-2iHGTA0U-GgZctt9At3uCQCLhl_sPVxJYJOpGYQXNRNOMfBubTCiXOWo4lDmN5y4aMoJyHceR5gYDsHV4J3mMBkC2zq59o6D8w" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="" data-original-height="1256" data-original-width="1256" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEg9dUs7LPJ9gQWekesHZv__yrBEEZWf0DwhFkz9u-EE9s_51hICFWbbQzuwSPFSA6-IUQigUCwcKw9LfAjncxKySEg-2iHGTA0U-GgZctt9At3uCQCLhl_sPVxJYJOpGYQXNRNOMfBubTCiXOWo4lDmN5y4aMoJyHceR5gYDsHV4J3mMBkC2zq59o6D8w" width="240" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">The forbidden hole</td></tr></tbody></table>In my opinion this device is booby-trapped. It is built in such a way that there is a user-facing slot that looks very similar to the slot we know from almost every smartphone produced in the past decade. It is a plastic tray with a small hole. The hole can be used to insert a paperclip so that the tray can be ejected. And indeed, the tray is a sim-card slot. However: <b>inserting a paperclip in the hole instantly renders your device useless. </b></div><div><b><br /></b></div><div>As soon as you insert a paper clip a tamper mechanism is triggered. This mechanism supposedly erases some battery-backed secure storage or burns fuses. Either way the device will not boot and SumUp will void your warranty. </div><div><br /></div><div>Having this slot in here raises the question: if the slot renders the device unusable, why is it even there? Because if the slot would be populated by an employee <i>before</i> the battery is connected for the first time, the back cover is off. So inserting a sim in an internal slot/motherboard slot would be perfectly feasible in that case. </div><div><br /></div><div>And even if there would be a valid reason (for example: the anti tamper mechanism is only armed after the device is powered up. The device is assembled in a single location. Local distributors put in the sim cards and seal up the packaging of the product) I can't help but wonder why there isn't a sticker over the sim slot (or the hole) that tells the user:</div><div><br /></div><blockquote><div>"Removing the sim tray will trigger the tamper detection system in this device". </div></blockquote><p>That would have been grand, SumUp. None of the booklets in the packaging seem to mention this. Some people might even think this is a "factory reset" hole. And press it because their device is malfunctioning or they want to sell it to someone else.</p><p>Other people on the internet have reported that not charging the device for an extended period of time (like: 6 months?) may trigger one of the tamper detection mechanisms, as well as shocks (due to accidentally dropping the device for example). In all of these cases you're SOL. SumUp has no interest in refurbishing/repurposing these devices and they will not give you a discount for sending it back. </p><p>Repurposing the hardware is pretty difficult since most of the parts that can be easily disassembled have no data sheets or mentions at all on the internet. </p><h3 style="text-align: left;">Disassembly and teardown</h3><div style="text-align: left;">Since I think I got my point across I guess the only thing left to do is share some teardown pictures! </div><div style="text-align: left;"><br /></div><div style="text-align: left;">To disassemble your SumUp 3G payment terminal start by unscrewing the two screws on the back of the device. Then slide the back cover downwards. You don't have to apply a lot of force to do this. I broke one of the legs because I was pulling on the cover.</div><div style="text-align: left;"><br /></div><p style="text-align: left;"><b>Modem and battery</b></p><div style="text-align: left;"><br /></div><div style="text-align: left;"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEig571BsmpOGJLS-Kiu1FHuX_9p-9ZPbMcPHBpyli-MYLZ6_WI7jOh8shgA6AgzumBP537X5RhI7-UhE5lm8dtw4U1-ElrueAPSfAFBkxMJPlwqSxCsrAlHBfjyJOD29y24N8pmRCe0bsXIBpCc2vhT40tcYtZRod2ZPP-JdEjVk1dhsG-iESCd8mL-CQ" style="margin-left: auto; margin-right: auto;"><img alt="" data-original-height="638" data-original-width="1024" height="124" src="https://blogger.googleusercontent.com/img/a/AVvXsEig571BsmpOGJLS-Kiu1FHuX_9p-9ZPbMcPHBpyli-MYLZ6_WI7jOh8shgA6AgzumBP537X5RhI7-UhE5lm8dtw4U1-ElrueAPSfAFBkxMJPlwqSxCsrAlHBfjyJOD29y24N8pmRCe0bsXIBpCc2vhT40tcYtZRod2ZPP-JdEjVk1dhsG-iESCd8mL-CQ=w200-h124" width="200" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">The Quectel modem with <br />some redacted unique numbers. </td></tr></tbody></table>You will be greeted by a cellular modem, in my case a <b>Quectel <a href="https://www.quectel.com/product/lte-eg91-series" rel="nofollow" target="_blank">EG91-EX</a></b>. This is an LTE (4G) modem with a USB 2.0 interface. The modem in question isn't very special, it is able to do 10mbps down and 5mbps up on LTE and it's an LTE CAT 1 IoT module. The flex cable connects the modem to the mother board and also carries the sim card signals (since the sim card slot is on the mother board). </div><div style="text-align: left;"><br /></div><div style="text-align: left;">Interestingly this device can do way higher speeds (according to the product brochure) when it's used on a DC-HSPA+ network (42mbps down, 5.76mbps up). If I recall correctly this is what we used to call 3.5G.</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjnG8hdquFLrdypuZJnO5erYn-I4ra-_JF68UcbioNrUnXNpVbGtRH3YjHwnTs8KmyNbDv3sdgadtDXVPJ6WR5NrqvrLYr1Hcb2wpQYy89KquOGyAmywVLRoS3ccC7k6T6o56HLHZwermakhHrz8eNNscMmPE7EHhc6eLCi2YkQbk3QZFXYhGjwD6RQ4w" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" data-original-height="888" data-original-width="1536" height="124" src="https://blogger.googleusercontent.com/img/a/AVvXsEjnG8hdquFLrdypuZJnO5erYn-I4ra-_JF68UcbioNrUnXNpVbGtRH3YjHwnTs8KmyNbDv3sdgadtDXVPJ6WR5NrqvrLYr1Hcb2wpQYy89KquOGyAmywVLRoS3ccC7k6T6o56HLHZwermakhHrz8eNNscMmPE7EHhc6eLCi2YkQbk3QZFXYhGjwD6RQ4w=w214-h124" width="214" /></a></div>Next up is the battery, which can be easily removed. Just unclip the connector from the motherboard. The battery is an Amperex Technology PS-GB-304583-010H. It's a 1200mHh (4.44Wh) Lithium Ion cell and it's pretty thin! <br /><br /></div><div style="text-align: left;"><br /></div><h4 style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEidPl29IwhnCFeWIHXJ4KD1Ra2SgmKcs7EOT8cWYDD6yT10wX2kgCw0jIAkMub_MZje6kHH6l65Q4QQcrVhCaEZgcyWhHE-Cqzd2kwJeBlmmIypC8JmFun-wO_x69aKjFii2BRSp9UU0nwO9e3HVGUrJD78HUrIncmemK-NTq80J5r3werhJBrCl43LCg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" data-original-height="893" data-original-width="1536" height="186" src="https://blogger.googleusercontent.com/img/a/AVvXsEidPl29IwhnCFeWIHXJ4KD1Ra2SgmKcs7EOT8cWYDD6yT10wX2kgCw0jIAkMub_MZje6kHH6l65Q4QQcrVhCaEZgcyWhHE-Cqzd2kwJeBlmmIypC8JmFun-wO_x69aKjFii2BRSp9UU0nwO9e3HVGUrJD78HUrIncmemK-NTq80J5r3werhJBrCl43LCg" width="320" /></a></div><br /></h4><h4 style="text-align: left;"><br /></h4><h4 style="text-align: left;"><br /><br /></h4><h4 style="text-align: left;"><br /></h4><h4 style="text-align: left;"><br /></h4><h4 style="text-align: left;">Motherboard back side</h4><div style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjxYfYH-5Lvosud1a4Oy6fcUwrXHIlLWWqmBFXU5TtodeBgDIFIEa5xoQ_pRqLTh-4sX9iBphPuzcJ0fdtaZpzXHuj79nqIbmsb5wND6oDiGIszd8I6IbuMYnBhH18jD2E_H--NGHW-xyPcrhdD03VWR28apj5QohHEZjJOTYk3f3bs4rFvjQoiMujphA" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="" data-original-height="1457" data-original-width="2048" height="228" src="https://blogger.googleusercontent.com/img/a/AVvXsEjxYfYH-5Lvosud1a4Oy6fcUwrXHIlLWWqmBFXU5TtodeBgDIFIEa5xoQ_pRqLTh-4sX9iBphPuzcJ0fdtaZpzXHuj79nqIbmsb5wND6oDiGIszd8I6IbuMYnBhH18jD2E_H--NGHW-xyPcrhdD03VWR28apj5QohHEZjJOTYk3f3bs4rFvjQoiMujphA" width="320" /></a></div>From here on I forgot to take a few pictures, but since the device is useless at this point anyway I don't think anyone really cares about how it was disassembled any way.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">This is most of the "back" side of the motherboard (the side that you see if you lift the back cover off). One of the most interesting things I noticed is that there is an ESP-WROOM-02U for the WiFi connectivity. I wouldn't have expected to see such a ubiquitous device in a "secure design" like this. Seems like an easy attack vector in a payment system. </div><div style="text-align: left;"><br /></div><div style="text-align: left;">There also seems to be a separate bluetooth chip, a TAIYO YUDEN <a href="https://nl.mouser.com/datasheet/2/396/TY_BLE_Overview_V1_8_20180530-1324374.pdf" rel="nofollow" target="_blank">EYSHCNZXZ </a>Bluetooth 4.2 Low Energy module. These seem to be based on nRF chips by Nordic.<br /><br />On the left we can see a battery (cell with the yellow insulation) that is presumably used to keep the CPU awake so it can trigger the tamper detection if the Lithium Ion battery is fully depleted.</div><div style="text-align: left;"><br /></div><p style="text-align: left;"><b>Main CPU (+ bootloader diagnostics)</b></p><div style="text-align: left;">The main CPU seems to be a <a href="https://www.maximintegrated.com/en/products/microcontrollers/MAX32552.html" rel="nofollow" target="_blank">MAX32552</a> which is a "DeepCover Secure ARM Cortex-M3 Flash Microcontroller". Among the <a href="https://www.maximintegrated.com/en/products/microcontrollers/MAX32552.html/product-details/tabs-3" rel="nofollow" target="_blank">chip features</a> we can see:</div><div style="text-align: left;"><ul style="text-align: left;"><li style="box-sizing: border-box;">6 External Tamper Sensors with Independent Random Dynamic Patterns</li><li style="box-sizing: border-box;">256-Bit Flip-Flop-Based Battery-Backup AES Key Storage</li><li style="box-sizing: border-box;">Temperature and Voltage Tamper Monitor</li><li style="box-sizing: border-box;">Secure Boot Loader with Public Key Authentication</li></ul><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhBcoLRAMuHuKjSHhIkdRd_peeAJfILSdnbMfNMPxCOO_oQSzxD8PfJJhtasBYtiLFE1t-mMg1qBMIVgk8rnU2tV3OmmZvnNl0XyJT3jXg2-HJcXgW2oUIR7K1LI5CtHy6ZwTm9J6uxyu3ehT_j2Pp9jso1q6PeHDRsI-upxy-9jdyQa8chfyQgUFtsaA" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" data-original-height="1200" data-original-width="1536" height="211" src="https://blogger.googleusercontent.com/img/a/AVvXsEhBcoLRAMuHuKjSHhIkdRd_peeAJfILSdnbMfNMPxCOO_oQSzxD8PfJJhtasBYtiLFE1t-mMg1qBMIVgk8rnU2tV3OmmZvnNl0XyJT3jXg2-HJcXgW2oUIR7K1LI5CtHy6ZwTm9J6uxyu3ehT_j2Pp9jso1q6PeHDRsI-upxy-9jdyQa8chfyQgUFtsaA=w269-h211" width="269" /></a></div>Cool, so that probably explains the D0 to D5 on the "failure diagnostics" screen that you can get in to by pressing "3" on the "Device Blocked" screen. I remember that D1 was the Sim card holder, so it's possible that SH stands for Sim Holder, but that's just speculation. </div><div><br /></div><div>Any "sensor" with an inverted background color has been triggered. I've managed to trigger only four out of the six. So I'm still looking for resources on how to trigger D0 (BT?) and D5 (BH?). </div><div><br /></div><div>Furthermore we now speculate that as soon as any tamper sensor is triggered the AES key storage is cleared which prevents the device from booting at all (since it's using Secure Boot). This also explains why SumUp can't re-use the motherboard after any of the mechanisms are triggered. </div><div><br /></div><div>Below the triggered sensors on the display we can see the date and time that the CPU was rendered useless. This is the time when the <i>first</i> sensor was triggered. Any additional triggers will not update the date and time. </div><div><br /></div><p style="text-align: left;"><b>Card reader tamper shield</b></p><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjJnwR0vYy9TliLZ5etBaTZ7TyRkBwo0ZwXdavg3QZIYFXkAr-9THGXx8CjhXiFUMBGZFG9EmZORiYO43Be9Ozjrwnygd_gWv1JEBonzcOJoFgnGcCR9smZD3uHOT8G8VQ1g01mFZ7bnIkwUpGq11aBRpMKC9pAmJU7gXq7dZZP-MMuVFI_nyTGRMfarw" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="" data-original-height="1254" data-original-width="1672" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEjJnwR0vYy9TliLZ5etBaTZ7TyRkBwo0ZwXdavg3QZIYFXkAr-9THGXx8CjhXiFUMBGZFG9EmZORiYO43Be9Ozjrwnygd_gWv1JEBonzcOJoFgnGcCR9smZD3uHOT8G8VQ1g01mFZ7bnIkwUpGq11aBRpMKC9pAmJU7gXq7dZZP-MMuVFI_nyTGRMfarw" width="320" /></a></div>There is also a tamper shield around the card reader module. It's a very interesting mesh that prevents any poking around. The foil seems to be sticked to a plastic frame and I noticed some air bubbles between the foil and the plastic frame. In addition I saw a bit of damage to the foil at the bottom part that was already present when I opened the device. </div><div><br /></div><div>The idea with these meshes is that the traces all conduct electricity. As soon as the resistance across the mesh changes, the tamper mechanism triggers. I wonder if a big magnet would be able to trigger this mechanism as well. <div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEglQI47txTfaYqQP7aPBQ7qA4kkFD4mGtzss63lRU63yNr-we6KToTZqifDiTpjoBIkUR2ScH8t-tYXea7WM3N-M1f4M4VS12LqWA3d1FjvRlYAmWCbnQQIE79tL5vCNmKB_mNkfag9hXV-3ClX3-aN_0-sHfbK3VegQIymcu8RM8-XWOeTeOFJLWcjYQ" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img alt="" data-original-height="3448" data-original-width="4592" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEglQI47txTfaYqQP7aPBQ7qA4kkFD4mGtzss63lRU63yNr-we6KToTZqifDiTpjoBIkUR2ScH8t-tYXea7WM3N-M1f4M4VS12LqWA3d1FjvRlYAmWCbnQQIE79tL5vCNmKB_mNkfag9hXV-3ClX3-aN_0-sHfbK3VegQIymcu8RM8-XWOeTeOFJLWcjYQ" width="320" /></a></div></div><div><br /></div><div>Underneath the shield we can see the actual card reader. I couldn't find a model number on the black housing.</div><div><br /></div><div>Here we can also see the gold fingers (five on the left, two on the right) that connected to the underside of the card reader tamper shield. The underside of the tamper mesh has zebra strips. </div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><p style="text-align: left;"><b>Other parts</b></p><div><div class="separator" style="clear: both; text-align: center;"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhQMWgRd6-zw-ECvPo_cilCpeaEWGsccDWqdeu9IJTgxiQxR6hOZzkIm50OkL8BpOl-mA0KWodGP6F7v5qHCM8xowiQVchqUvtFG4WwSyDyVT4isXc4JgDh7IVEAP_NwfeDHiX2DTzcEVkG9Osz4P1YA_QNV8HEAaLmP-2b-ygGikeJGpeGGsxTCDYnwg" style="margin-left: auto; margin-right: auto;"><img alt="" data-original-height="3448" data-original-width="4592" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEhQMWgRd6-zw-ECvPo_cilCpeaEWGsccDWqdeu9IJTgxiQxR6hOZzkIm50OkL8BpOl-mA0KWodGP6F7v5qHCM8xowiQVchqUvtFG4WwSyDyVT4isXc4JgDh7IVEAP_NwfeDHiX2DTzcEVkG9Osz4P1YA_QNV8HEAaLmP-2b-ygGikeJGpeGGsxTCDYnwg" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">The flex-board chip that probably drives<br /> the touch screen input.<br />FPC-MTP240-014DAAMFIL<br /><br /></td></tr></tbody></table></div><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh9Jda5CRmw-i_y5pPHTE5_Ewyev39I-CCXDZbWPxaCXuBrzgtvoeyj1g6ijTRyQqGZT7Pdtkbua9GD3C2EpJObViHkMEOnWnJToRO_vGX3ug6vAKJ77runaAFEaTB8-7ya1X_EvxHVLBO14zxvtHN4scor490nN76MXDL3pFNQxbzB5RavDGomzBo9HA" style="margin-left: auto; margin-right: auto;"><img alt="" data-original-height="3448" data-original-width="4592" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEh9Jda5CRmw-i_y5pPHTE5_Ewyev39I-CCXDZbWPxaCXuBrzgtvoeyj1g6ijTRyQqGZT7Pdtkbua9GD3C2EpJObViHkMEOnWnJToRO_vGX3ug6vAKJ77runaAFEaTB8-7ya1X_EvxHVLBO14zxvtHN4scor490nN76MXDL3pFNQxbzB5RavDGomzBo9HA" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Part number on the flex cable that carries display<br />signals<br />YTC240DLBU-02-300C0V3</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjoQhcVJeVZ8-cRXMEBqqijfjcg7Kw8fiBe9slaW8iK2QTTa2oOB8mrpOwv8awQg3LtrgPW-nYzjAZgpjvBlh2XmTJuLy1pWlgD5Q8uUxnsBfDQCMV15c94q6IOVQfdynwVkNC7_hUs3qmFk-De6PgcfsLBIm_0OdMUpd3pvxQ-Lo5kNn3jJZAj4HSkCQ" style="margin-left: auto; margin-right: auto;"><img alt="" data-original-height="3448" data-original-width="4592" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEjoQhcVJeVZ8-cRXMEBqqijfjcg7Kw8fiBe9slaW8iK2QTTa2oOB8mrpOwv8awQg3LtrgPW-nYzjAZgpjvBlh2XmTJuLy1pWlgD5Q8uUxnsBfDQCMV15c94q6IOVQfdynwVkNC7_hUs3qmFk-De6PgcfsLBIm_0OdMUpd3pvxQ-Lo5kNn3jJZAj4HSkCQ" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Other side of the display signal flex cable:<br />FPC-YTC2400DLBU-02-200N</td></tr></tbody></table><div class="separator" style="clear: both; text-align: center;"><br /></div><h3 style="text-align: left;">Conclusion</h3><div>I'm a bit disappointed that SumUp doesn't make customers aware of the tamper detection mechanism and the kind of things that can trigger it. People these days have put a SIM card in their smartphone at least once in their life or they have seen people do it for them. Curiosity isn't a bad thing. And I'm completely fine with SumUp deciding "if you tamper with our device, we will void the warranty". But please, pretty please: be upfront in what kinds of actions can trigger the tamper detection mechanism.</div><div><br /></div><div>This is a <i>mobile</i> payment device. Customers will have this device in their hands if they insert their payment card in the bottom and obviously every now and then a device is dropped. That's unfortunate, but nothing that a refurbishment couldn't solve. </div><div><br /></div><div>Right now, a small business would need to have a second device on standby if they rely on card payments simply because the tamper mechanism might trigger. This second device has to be charged every few months to prevent the device from bricking itself. Imagine a church that has an annual charity sale that is run by volunteers. They decide to use a SumUp device and after the event they store it in a box for next year. Next year the device is bricked because the battery depleted over time. Why isn't the user informed about this tamper mechanism? Why do people have to find out on their own and bear the cost of purchasing another of these booby-trapped devices?</div><div><br /></div><div>And don't just display <i>some</i> things that can trigger the mechanism on a FAQ page on your website. Place a sticker on the product packaging. Place it over the sim slot. Place it over the screen. I don't care.</div><div><br /></div><div><b>Just make sure that people like me (who DO read thesestickers) are aware of the actions that can trigger the tamper detection sensors.</b></div><div><br /></div><div>Something like this:</div><div><b><br /></b></div><div><b><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgMGUU2itH87yGhKNXsvZpA6jeVdf9YYZcbmiRPRKIKJ4w6bVvKRRUa1hQ4H4TbW6BLWaJNUj1t7PpFj1D57D1geTBa6hcE8zrKbEQdXAqstpsQqGSplKmzC_jgvJwHEE56o6Gqu0V4Xhj70PeKNH0zlOWjYRIVjeONuD9-5lJpV45QxInb5LTEK2ytgA" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="402" data-original-width="641" height="201" src="https://blogger.googleusercontent.com/img/a/AVvXsEgMGUU2itH87yGhKNXsvZpA6jeVdf9YYZcbmiRPRKIKJ4w6bVvKRRUa1hQ4H4TbW6BLWaJNUj1t7PpFj1D57D1geTBa6hcE8zrKbEQdXAqstpsQqGSplKmzC_jgvJwHEE56o6Gqu0V4Xhj70PeKNH0zlOWjYRIVjeONuD9-5lJpV45QxInb5LTEK2ytgA" width="320" /></a></div></b></div></div></div><p></p>Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-88934958722235369162020-12-03T19:52:00.004+01:002020-12-03T20:02:30.729+01:00Modifying the Ubiquiti CRM Key to run Cloud Key firmwareThis is an extract from the information that I posted on the Ubiquiti forums in <a href="https://community.ui.com/questions/CRM-Point-custom-squashfs-image/0ed2515c-4dc9-42f1-9263-fdc3272ead53" rel="nofollow" target="_blank">this</a> topic. I'd like to be very clear that if you choose to run any of the commands on this page, you are doing this at your own risk. Don't proceed unless you're okay with potentially bricking your device without any way to recover.
<h2 style="text-align: left;">Background</h2>
I recently got a CRM Point (being well aware that it it not supported anymore by Ubiquiti) and started playing around with it. For the uninitiated: the Cloud Key is an ARM-based small computer that can be powered over POE. It uses the MediaTek mtk7623 SOC and has 2GiB of RAM memory. The point of the CRM Key was to install it at customers networks which allows a sysadmin to remotely manage compatible (Ubiquiti airMAX) network equipment. <div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_ABRWBvRPyVmb4Y7E8n3VPxR3w6KpLuQd6QJlRNJswH4qpFiEdQdIsjpSb4EuVxfo11KJjICRRDlaJf52YXjfDAJcOthwFYuidTKfDsnPk1UZGp412N20_TJSgWMk0PxuvfzpAHtzPrZW/s359/CRM.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="250" data-original-width="359" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_ABRWBvRPyVmb4Y7E8n3VPxR3w6KpLuQd6QJlRNJswH4qpFiEdQdIsjpSb4EuVxfo11KJjICRRDlaJf52YXjfDAJcOthwFYuidTKfDsnPk1UZGp412N20_TJSgWMk0PxuvfzpAHtzPrZW/w276-h192/CRM.jpg" width="276" /></a></div><br /></div><div>I noticed that the firmware isn't updated that regularly anymore which is sad. Because it has a limited amount of flash memory and any time I run <span style="font-family: courier;">apt-get update && apt-get upgrade -y</span> this fills the read-write partition. <div><br /></div><div>But most packages are so old that installing (for example) an up to date version of Java will take more than half of the available storage. Of course I had purchased this device because I intended to tinker with it. So I did exactly that. <br /><h2 style="text-align: left;">First exploration</h2>
I installed <span style="font-family: courier;"><a href="https://community.ui.com/questions/Installing-airControl-on-CRM-Point/a4f1fdcd-114a-4c06-a842-e56eff486570">CRM.mtk7623.v0.6.0.a670e69M.170615.0748.bin</a></span> on it (to my knowledge this is the latest firmware that was released for this hardware) and was happy to see that a clean install leaves 100% of space on the rw-partition. This got me thinking: if I can install the updated packages in the read-only partition this will leave the read-write partition almost empty!
Given that the read-only partition is situated at <span style="font-family: courier;">/dev/mmcblk0p6</span> I started trying some stuff out: </div>
<pre><code class="language-|bash">root@control-point:/data# dd if=/dev/mmcblk0p6 of=/data/dd.img
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 101.841 s, 10.5 MB/s
root@control-point:/data# dd if=/data/dd.img of=/dev/mmcblk0p6
2097152+0 records in
2097152+0 records out
1073741824 bytes (1.1 GB) copied, 242.271 s, 4.4 MB/s
</code></pre>
<div>So writing to the read-only partition directly does not seem to be blocked in any way. After a reboot everything still works just fine! But interestingly enough the partition is 1.1GB while the size of the read-only filesystem as reported by df is only 207MB. This means that there is some potential room for additional tools and packages! </div><div><br /></div><h2 style="text-align: left;">First attempt at a 'custom rom'</h2><div>I extracted the squashfs from <code>/dev/mmvblk0p6</code> onto <code>/data/</code>, then ran mksquashfs on the squashfs-root folder in <code>/data</code> and then I proceeded to dd the resulting squashfs back to /dev/mmvblk0p6. While the filesystem is mostly fine, somehow my root/ubnt user got borked and I can't log in using ssh :(. I can however log in to the AirControl web UI. My theory is that this was an issue caused by the layer _under_ the rw-overlay changing. Therefore the stuff on top became invalid. Trashing the entire rw-layer fixes that. </div><div><br /></div><div><br /></div><div>How to start modifying your read-only squashfs:
<ul>
<li>ssh to your crm point</li>
<li>cd to <code>/data</code> directory</li>
<li><code>apt-get update && apt-get install squashfs-tools</code></li>
<li><code>unsquashfs /dev/mmcblk0p6</code></li>
<li>Follow the step on <a href="https://wiki.debian.org/chroot#Configuration" rel="nofollow" target="_blank">this page</a> about the policy.d file</li>
<li>Mount /dev, /dev/pts, /proc sections according to the <a href="https://wiki.debian.org/chroot#Copy_and_Paste" rel="nofollow" target="_blank">copy-pasta</a> here</li>
<li><code>chroot squashfs-root</code></li>
<li><code>mkdir /tmp</code></li>
</ul>
At this point you can run <code>apt-get</code> commands as if you are actually "running this system". So this includes adding packages, Fixing <code>/etc/apt/sources.list</code> to also contain jessie-backports, updating existing packages. Just make sure that all of this will still fit in the 1.1GB partition that it will eventually need to squeeze in to. In my case I also removed the aircontrol and postgres packages.
Then start your cleanup:
<pre><code class="language-|bash">rm -rf /tmp
apt-get clean
# Next line makes sure that on factory reset a new SSH key is generated
rm /etc/ssh/ssh_host_rsa_key.pub /etc/ssh/ssh_host_dsa_key.pub /etc/ssh/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ed25519_key.pub
rm -rf /usr/sbin/policy-rc.d
history -c
exit #(this is where you leave your chroot)
umount /proc /dev/pts /dev #In my case some of them didn't want to unmount. If this happens, just reboot the CRM point.
mksquashfs /data/squashfs-root root.sqfs
dd if=/data/root.sqfs of=/dev/mmcblk0p6
</code></pre>
From this point on any command you run will likely fail because the rofs was overwritten while mounted. This confuses the system which is understandable. So just pull the power, plug it in again, and attempt to reset the device with a paperclip or something. It should boot up pretty fast and you are now running your custom squashfs image!
<h2 style="text-align: left;">Next steps</h2>
So given that I was able to modify my squashfs I started to wonder... What if I could extract the kernel and rootfs from the cloud key firmware update and copy it to the flash of my CRM Point using DD? Would the kernel crash? Would the bootloader do some checksum check on the kernel partition? I didn't know, but I wanted to try. Especially since a lot of people on the forum over the years have said "you can't", "you'll brick it" and things like that. And I am pretty stubborn. </div><div><br /></div><div> So first I tried to cross-flash the Cloud Key the firmware using ubnt-systool fwupdate but that failed. This is because the tool that checks which product this is probably uses data from one of the partitions that I didn't touch. But that's actually perfect because I wouldn't want an accidental update to brick my hacked cloud key, so I guess this worked out just fine. </div><h3 style="text-align: left;"> 1. Determine flash layout</h3><div>So as most people probably already know, embedded devices running linux usually have multiple partitions. In order to do some analysis on firmwares the tool dd is very useful to make backups of partitions so that if you screw up but you can get the device to boot to some kind of recovery you can restore it. So let's take a look at the partitions:
<pre><code class="language-|bash">root@control-point:~# parted /dev/mmcblk0
GNU Parted 3.2
Using /dev/mmcblk0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) p
Model: MMC 004GE0 (sd/mmc)
Disk /dev/mmcblk0: 3937MB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 262kB 786kB 524kB uboot
2 786kB 1049kB 262kB config
3 1049kB 1311kB 262kB factory
4 1311kB 34.9MB 33.6MB kernel
5 34.9MB 68.4MB 33.6MB recovery
6 68.4MB 1142MB 1074MB rootfs
7 1142MB 2753MB 1611MB ext4 appdata
8 2753MB 3937MB 1185MB ext4 userdata
</code></pre>
As we can see there are quite some partitions. Let's back them all up first. </div><div><br /></div><h3 style="text-align: left;"> 2. Back up all partitions</h3><div>This makes a copy of every individual partition on to your SD card (which should be mounted at /data)
<pre><code class="language-|bash">root@control-point:~# dd if=/dev/mmcblk0p1 of=/data/mmcblk0p1.img
1024+0 records in
1024+0 records out
524288 bytes (524 kB) copied, 0.0360363 s, 14.5 MB/s
root@control-point:~# dd if=/dev/mmcblk0p2 of=/data/mmcblk0p2.img
512+0 records in
512+0 records out
# repeat for every partition number (so till mmcblk0p8)
</code></pre>
Next I copied these files from the SD card to my NAS, but of course just putting the SD-card in a SD-card reader is also perfectly fine.
<pre><code class="language-|bash">
root@control-point:/data# scp mmc* root@192.168.1.13:/mnt/user/FliX/Ubiquiti/
The authenticity of host '192.168.1.13 (192.168.1.13)' can't be established.
ECDSA key fingerprint is c4:0f:f2:89:57:df:bb:85:ee:ba:fb:41:e6:d3:90:9e.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.13' (ECDSA) to the list of known hosts.
root@192.168.1.13's password:
mmcblk0p1.img 100% 512KB 512.0KB/s 00:00
mmcblk0p2.img 100% 256KB 256.0KB/s 00:00
mmcblk0p3.img 100% 256KB 256.0KB/s 00:00
mmcblk0p4.img 100% 32MB 8.0MB/s 00:04
mmcblk0p5.img 100% 32MB 10.7MB/s 00:03</code></pre></div><h3 style="text-align: left;"> 3. Examining the DD-images and the firmware files</h3><div>For this I used the tool binwalk. This walks through a firmware image and looks for certain signatures that are known to identify certain 'parts' of a firmware image. So first I did this for the latest firmware updates for the UCK and CRM Point:
<pre><code class="language-|bash">
$ binwalk UCK.mtk7623.v1.1.13.818cc5f.200430.0950.bin
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Ubiquiti firmware header, header size: 264 bytes, ~CRC32: 0x8ED3EC98, version: "UCK.mtk7623.v1.1.13.818cc5f.200430.0950"
260 0x104 Ubiquiti partition header, header size: 56 bytes, name: "PARTkernel", base address: 0x00000000, data size: 0 bytes
324 0x144 uImage header, header size: 64 bytes, header CRC: 0x3960E04E, created: 2020-04-30 10:00:43, image size: 7079048 bytes, Data Address: 0x80008000, Entry Point: 0x80008000, data CRC: 0x7D24D70D, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux-3.10.20-ubnt-mtk"
14642 0x3932 xz compressed data
14863 0x3A0F xz compressed data
7079436 0x6C060C Ubiquiti partition header, header size: 56 bytes, name: "PARTrootfs", base address: 0x00000002, data size: 0 bytes
7079500 0x6C064C Squashfs filesystem, little endian, version 4.0, compression:gzip, size: 349822683 bytes, 29395 inodes, blocksize: 262144 bytes, created: 2020-04-30 10:00:22
$ binwalk CRM.mtk7623.v0.6.0.a670e69M.170615.0748.bin
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Ubiquiti firmware header, header size: 264 bytes, ~CRC32: 0x604E5185, version: "CRM.mtk7623.v0.6.0.a670e69M.170615.0748"
260 0x104 Ubiquiti partition header, header size: 56 bytes, name: "PARTkernel", base address: 0x00000000, data size: 0 bytes
324 0x144 uImage header, header size: 64 bytes, header CRC: 0xE24B3D5A, created: 2017-06-15 14:57:10, image size: 6586640 bytes, Data Address: 0x80008000, Entry Point: 0x80008000, data CRC: 0x2526FE9E, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux-3.10.20-ubnt-mtk"
14642 0x3932 xz compressed data
14863 0x3A0F xz compressed data
6587028 0x648294 Ubiquiti partition header, header size: 56 bytes, name: "PARTrootfs", base address: 0x00000002, data size: 0 bytes
6587092 0x6482D4 Squashfs filesystem, little endian, version 4.0, compression:gzip, size: 216177339 bytes, 17413 inodes, blocksize: 262144 bytes, created: 2017-06-15 14:56:50
</code></pre>
So clearly the first 'segments' are ubiquiti specific. Then at offset 324 we see the declaration of a 7079048 byte image. Given that the read-only filesystem is a lot larger than 7 Megabytes this is probably the kernel. The last entry in the table is the actual squashfs filesystem. And this is where it gets interesting! </div><div><br /></div><h3 style="text-align: left;"> 4. Testing a theory </h3><div>So let's assume that the images in the firmware update files are being copied 1:1 to the partitions (so: kernel part goes to mmcblk0p4, rofs goes to mmcblk0p6) and no other security/encryption happens in that process. That would mean that we can test this theory by comparing the kernel partition image we created on the CRM Point to the kernel partition image in the firmware update file.
<code>dd if=CRM.mtk7623.v0.6.0.a670e69M.170615.0748.bin skip=324 count=6586704 iflag=count_bytes bs=1 of=extracted_crm_kernel</code>
So let's test that theory. So we're copying data starting at offset 324 (where the uImage header starts) and we take image size + header size as the count argument.
Comparing the extracted_crm_kernel file to mmcblk0p4.img confirmed my suspicion. The only difference between the two files is that the partition we extracted from the CRM is filled with zero's where the kernel data ends. For obvious reasons the firmware update does not contain all the 0's.
We're going to take a wild guess and assume that this is also the case for the data partition:
<pre style="text-align: left;"><code class="language-|bash">
dd if=UCK.mtk7623.v1.1.13.818cc5f.200430.0950.bin skip=324 count=7079112 iflag=count_bytes bs=1 of=extracted_uck_kernel
dd if=UCK.mtk7623.v1.1.13.818cc5f.200430.0950.bin skip=1769875 bs=4 of=extracted_uckrootfs.squashfs
</code></pre><h3 style="text-align: left;">
5. Crafting our update file</h3></div><div>Earlier in this post thread I showed that using dd to overwrite a partition works just fine, but everything that reads from the partition (especially the overlay one) is screwed up because the underlying data is completely different. Unfortunately swapping a kernel and not the filesystem may also result in a brick. But the kernel and rootfs partitions have a recovery partition in between. Initially I wanted to make a single file that we can write with dd that includes the kernel, recovery and rootfs partitions. But I took a quick peek in <code>mmcblk0p5.img</code> and realised this partition is filled with zeros. This explains why people have no way to recover once they brick this thing :D.
<pre><code class="language-|bash">
$ cp mmcblk0p5.img extracted_uck_kernel_padded.img # take 32MiB img filled with zeroes
$ dd if=extracted_uck_kernel conv=notrunc of=extracted_uck_kernel_padded.img
13826+1 records in
13826+1 records out
7079112 bytes (7.1 MB, 6.8 MiB) copied, 0.177849 s, 39.8 MB/s
$ dd if=mmcblk0p5.img >>extracted_uck_kernel_padded.img # insert 32MiB of zeroes
65536+0 records in
65536+0 records out
33554432 bytes (34 MB, 32 MiB) copied, 1.16823 s, 28.7 MB/s
$ dd if=extracted_uckrootfs.squashfs >>extracted_uck_kernel_padded.img # then append the squashfs
683248+1 records in
683248+1 records out
349823248 bytes (350 MB, 334 MiB) copied, 11.6135 s, 30.1 MB/s
</code></pre>
So next up: copy <code>extracted_uck_kernel_padded.img</code> on to the sdcard so we can flash it!
6. Flashing
This is the part where everything either succeeds, or fails. This is your last chance to choose for safety. If you enter these commands and you brick your device, you are on your own. Neither Ubiquiti nor I can provide support to you if this fails.
First off, let's determine where we have to write this file to.
<pre><code class="language-|bash">
root@control-point:/# parted /dev/mmcblk0 'unit s print'
Model: MMC 004GE0 (sd/mmc)
Disk /dev/mmcblk0: 7690240s
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 512s 1535s 1024s uboot
2 1536s 2047s 512s config
3 2048s 2559s 512s factory
4 2560s 68095s 65536s kernel
5 68096s 133631s 65536s recovery
6 133632s 2230783s 2097152s rootfs
7 2230784s 5376511s 3145728s ext4 appdata
8 5376512s 7690206s 2313695s ext4 userdata
</code></pre>
Ok, cool. So because we have an image file that spans kernel (32MiB), recovery (32MiB) and rootfs (the rest) we can just tell dd to start writing at offset 2560 until we reach the end of the file. This works because the new rootfs is larger than the previous one. Otherwise it would have been wiser to append some more 00's at the end of our image just to make sure we don't have weird garbage at the end of our actual partition data.
<pre><code class="language-|bash">
root@control-point:/# dd if=/data/extracted_uck_kernel_padded.img of=/dev/mmcblk0 \
seek=2560
814320+1 records in
814320+1 records out
416932112 bytes (417 MB) copied, 60.8669 s, 6.8 MB/s
</code></pre>
So from this point your stick will be a little confused. SSH logins might fail, and that kind of good stuff. For me just a normal paperclip-reset wasn't enough, I had to do a reset from the web interface as well (or SSH... not 100% sure anymore). But after the reset this thing behaves like a UniFi Cloud Key! Enjoy!</div></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFyHJSoSs_lYLiPEMA-gPwkx6J3iHQMQHPGoPc5QOtP0aH0huv6TjBjG8I8rUQep3OCdeb2vA7vEhOz6Vamzc7s0EWlMrh7JQH44oGYhD6xTKnEnncdgxCR0v6BpC5m037h5sqBAoanLvh/s1568/Screenshot+2020-12-03+at+19.47.18.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="508" data-original-width="1568" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFyHJSoSs_lYLiPEMA-gPwkx6J3iHQMQHPGoPc5QOtP0aH0huv6TjBjG8I8rUQep3OCdeb2vA7vEhOz6Vamzc7s0EWlMrh7JQH44oGYhD6xTKnEnncdgxCR0v6BpC5m037h5sqBAoanLvh/w640-h208/Screenshot+2020-12-03+at+19.47.18.png" width="640" /></a></div><br /><div><br /></div>Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com3tag:blogger.com,1999:blog-3004394666862334139.post-69640573003603154052018-12-06T18:21:00.001+01:002018-12-06T21:39:09.380+01:00Customise Hue Bulb Startup Behaviour after a power cut<style>@charset "UTF-8";@import 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0-alpha2/katex.min.css';code{color:#c7254e;background-color:#f9f2f4;border-radius:4px}code,kbd{padding:2px 4px}kbd{color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;box-shadow:none}pre{display:block;margin:0 0 10px;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}table{background-color:transparent}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr>td,.table>tbody>tr>th,.table>tbody>tr>td,.table>tfoot>tr>th,.table>tfoot>tr>td{padding:8px;line-height:1.4285714;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>th,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered,.table-bordered>thead>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>thead>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>thead>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>thead>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>thead>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>thead>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}fieldset{border:0;min-width:0}legend{display:block;width:100%;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{padding-top:7px}output,.form-control{display:block;font-size:14px;line-height:1.4285714;color:#555}.form-control{width:100%;height:34px;padding:6px 12px;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#777;opacity:1}.form-control:-ms-input-placeholder{color:#777}.form-control::-webkit-input-placeholder{color:#777}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="date"],input[type="time"],input[type="datetime-local"],input[type="month"]{line-height:34px;line-height:1.4285714 \0}input[type="date"].input-sm,.form-horizontal .form-group-sm input[type="date"].form-control,.input-group-sm>input[type="date"].form-control,.input-group-sm>input[type="date"].input-group-addon,.input-group-sm>.input-group-btn>input[type="date"].btn,input[type="time"].input-sm,.form-horizontal .form-group-sm input[type="time"].form-control,.input-group-sm>input[type="time"].form-control,.input-group-sm>input[type="time"].input-group-addon,.input-group-sm>.input-group-btn>input[type="time"].btn,input[type="datetime-local"].input-sm,.form-horizontal .form-group-sm input[type="datetime-local"].form-control,.input-group-sm>input[type="datetime-local"].form-control,.input-group-sm>input[type="datetime-local"].input-group-addon,.input-group-sm>.input-group-btn>input[type="datetime-local"].btn,input[type="month"].input-sm,.form-horizontal .form-group-sm input[type="month"].form-control,.input-group-sm>input[type="month"].form-control,.input-group-sm>input[type="month"].input-group-addon,.input-group-sm>.input-group-btn>input[type="month"].btn{line-height:30px}input[type="date"].input-lg,.form-horizontal .form-group-lg input[type="date"].form-control,.input-group-lg>input[type="date"].form-control,.input-group-lg>input[type="date"].input-group-addon,.input-group-lg>.input-group-btn>input[type="date"].btn,input[type="time"].input-lg,.form-horizontal .form-group-lg input[type="time"].form-control,.input-group-lg>input[type="time"].form-control,.input-group-lg>input[type="time"].input-group-addon,.input-group-lg>.input-group-btn>input[type="time"].btn,input[type="datetime-local"].input-lg,.form-horizontal .form-group-lg input[type="datetime-local"].form-control,.input-group-lg>input[type="datetime-local"].form-control,.input-group-lg>input[type="datetime-local"].input-group-addon,.input-group-lg>.input-group-btn>input[type="datetime-local"].btn,input[type="month"].input-lg,.form-horizontal .form-group-lg input[type="month"].form-control,.input-group-lg>input[type="month"].form-control,.input-group-lg>input[type="month"].input-group-addon,.input-group-lg>.input-group-btn>input[type="month"].btn{line-height:46px}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;min-height:20px;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="radio"].disabled,fieldset[disabled] input[type="radio"],input[type="checkbox"][disabled],input[type="checkbox"].disabled,fieldset[disabled] input[type="checkbox"],.radio-inline.disabled,fieldset[disabled] .radio-inline,.checkbox-inline.disabled,fieldset[disabled] .checkbox-inline,.radio.disabled label,fieldset[disabled] .radio label,.checkbox.disabled label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-horizontal .form-group-lg .form-control-static.form-control,.input-group-lg>.form-control-static.form-control,.input-group-lg>.form-control-static.input-group-addon,.input-group-lg>.input-group-btn>.form-control-static.btn,.form-control-static.input-sm,.form-horizontal .form-group-sm .form-control-static.form-control,.input-group-sm>.form-control-static.form-control,.input-group-sm>.form-control-static.input-group-addon,.input-group-sm>.input-group-btn>.form-control-static.btn{padding-left:0;padding-right:0}.input-sm,.form-horizontal .form-group-sm .form-control,.input-group-sm>.form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.input-group-sm>.input-group-addon{height:30px;line-height:1.5}.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm,.form-horizontal .form-group-sm select.form-control,.input-group-sm>select.form-control,.input-group-sm>select.input-group-addon,.input-group-sm>.input-group-btn>select.btn{height:30px;line-height:30px}textarea.input-sm,.form-horizontal .form-group-sm textarea.form-control,.input-group-sm>textarea.form-control,.input-group-sm>textarea.input-group-addon,.input-group-sm>.input-group-btn>textarea.btn,select[multiple].input-sm,.form-horizontal .form-group-sm select[multiple].form-control,.input-group-sm>select[multiple].form-control,.input-group-sm>select[multiple].input-group-addon,.input-group-sm>.input-group-btn>select[multiple].btn{height:auto}.input-lg,.form-horizontal .form-group-lg .form-control,.input-group-lg>.form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.input-group-lg>.input-group-addon{height:46px;line-height:1.33}.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg,.form-horizontal .form-group-lg select.form-control,.input-group-lg>select.form-control,.input-group-lg>select.input-group-addon,.input-group-lg>.input-group-btn>select.btn{height:46px;line-height:46px}textarea.input-lg,.form-horizontal .form-group-lg textarea.form-control,.input-group-lg>textarea.form-control,.input-group-lg>textarea.input-group-addon,.input-group-lg>.input-group-btn>textarea.btn,select[multiple].input-lg,.form-horizontal .form-group-lg select[multiple].form-control,.input-group-lg>select[multiple].form-control,.input-group-lg>select[multiple].input-group-addon,.input-group-lg>.input-group-btn>select[multiple].btn{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:25px;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center}.input-lg+.form-control-feedback,.form-horizontal .form-group-lg .form-control+.form-control-feedback,.input-group-lg>.form-control+.form-control-feedback,.input-group-lg>.input-group-addon+.form-control-feedback,.input-group-lg>.input-group-btn>.btn+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.form-horizontal .form-group-sm .form-control+.form-control-feedback,.input-group-sm>.form-control+.form-control-feedback,.input-group-sm>.input-group-addon+.form-control-feedback,.input-group-sm>.input-group-btn>.btn+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-group:before{content:" ";display:table}.form-horizontal .form-group:after{content:" ";display:table;clear:both}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon{white-space:nowrap}.input-group-addon,.input-group-btn{width:1%;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm,.form-horizontal .form-group-sm .input-group-addon.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg,.form-horizontal .form-group-lg .input-group-addon.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{font-size:0;white-space:nowrap}.input-group-btn,.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.4285714;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>a:focus,.pagination>li>span:hover,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:hover,.pagination>.active>a:focus,.pagination>.active>span,.pagination>.active>span:hover,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open,.modal{overflow:hidden}.modal{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate3d(0,-25%,0);transform:translate3d(0,-25%,0);-webkit-transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.4285714px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.4285714}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{content:" ";display:table}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.hljs{display:block;overflow-x:auto;padding:.5em;background:#002b36;color:#839496;-webkit-text-size-adjust:none}.hljs-comment,.hljs-template_comment,.diff .hljs-header,.hljs-doctype,.hljs-pi,.lisp .hljs-string,.hljs-javadoc{color:#586e75}.hljs-keyword,.hljs-winutils,.method,.hljs-addition,.css .hljs-tag,.hljs-request,.hljs-status,.nginx .hljs-title{color:#859900}.hljs-number,.hljs-command,.hljs-string,.hljs-tag .hljs-value,.hljs-rules .hljs-value,.hljs-phpdoc,.hljs-dartdoc,.tex .hljs-formula,.hljs-regexp,.hljs-hexcolor,.hljs-link_url{color:#2aa198}.hljs-title,.hljs-localvars,.hljs-chunk,.hljs-decorator,.hljs-built_in,.hljs-identifier,.vhdl .hljs-literal,.hljs-id,.css .hljs-function{color:#268bd2}.hljs-attribute,.hljs-variable,.lisp .hljs-body,.smalltalk .hljs-number,.hljs-constant,.hljs-class .hljs-title,.hljs-parent,.hljs-type,.hljs-link_reference{color:#b58900}.hljs-preprocessor,.hljs-preprocessor .hljs-keyword,.hljs-pragma,.hljs-shebang,.hljs-symbol,.hljs-symbol .hljs-string,.diff .hljs-change,.hljs-special,.hljs-attr_selector,.hljs-subst,.hljs-cdata,.css .hljs-pseudo,.hljs-header{color:#cb4b16}.hljs-deletion,.hljs-important{color:#dc322f}.hljs-link_label{color:#6c71c4}.tex .hljs-formula{background:#073642}*,*:before,*:after{box-sizing:border-box}html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}images{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd{font-size:1em}code,kbd,pre,samp{font-family:monospace,monospace}samp{font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;margin-right:5px}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}.debug{background-color:#ffc0cb!important}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ir{background-color:transparent;border:0;overflow:hidden}.ir::before{content:'';display:block;height:150%;width:0}html{font-size:.875em;color:#373D49}html,body{font-family:Georgia,Cambria,serif;height:100%}body{font-size:1rem;font-weight:400;line-height:2rem}ul,ol{margin-bottom:.83999rem;padding-top:.16001rem}li{-webkit-font-feature-settings:'kern' 1,'onum' 1,'liga' 1;font-feature-settings:'kern' 1,'onum' 1,'liga' 1;margin-left:1rem}li>ul,li>ol{margin-bottom:0}p{padding-top:.66001rem;-webkit-font-feature-settings:'kern' 1,'onum' 1,'liga' 1;font-feature-settings:'kern' 1,'onum' 1,'liga' 1;margin-top:0}p,pre{margin-bottom:1.33999rem}pre{font-size:1rem;padding:.66001rem 9.5px 9.5px;line-height:2rem;background:-webkit-linear-gradient(top,#fff 0,#fff .75rem,#f5f7fa .75rem,#f5f7fa 2.75rem,#fff 2.75rem,#fff 4rem);background:linear-gradient(to bottom,#fff 0,#fff .75rem,#f5f7fa .75rem,#f5f7fa 2.75rem,#fff 2.75rem,#fff 4rem);background-size:100% 4rem;border-color:#D3DAEA}blockquote{margin:0}blockquote p{font-size:1rem;margin-bottom:.33999rem;font-style:italic;padding:.66001rem 1rem 1rem;border-left:3px solid #A0AABF}th,td{padding:12px}a{cursor:pointer;color:#35D7BB;text-decoration:none}a:hover,a:focus{border-bottom-color:#35D7BB;color:#dff9f4}img{height:auto;max-width:100%}.g{display:block}.g:after{clear:both;content:'';display:table}.g-b{float:left;margin:0;width:100%}.g{margin-left:-16px;margin-right:-16px}.g-b{padding-left:16px;padding-right:16px}.g-b--center{display:block;float:none;margin:0 auto}.g-b--right{float:right}.g-b--1of1{width:100%}.g-b--1of2,.g-b--2of4,.g-b--3of6,.g-b--4of8,.g-b--5of10,.g-b--6of12{width:50%}.g-b--1of3,.g-b--2of6,.g-b--4of12{width:33.333%}.g-b--2of3,.g-b--4of6,.g-b--8of12{width:66.666%}.g-b--1of4,.g-b--2of8,.g-b--3of12{width:25%}.g-b--3of4,.g-b--6of8,.g-b--9of12{width:75%}.g-b--1of5,.g-b--2of10{width:20%}.g-b--2of5,.g-b--4of10{width:40%}.g-b--3of5,.g-b--6of10{width:60%}.g-b--4of5,.g-b--8of10{width:80%}.g-b--1of6,.g-b--2of12{width:16.666%}.g-b--5of6,.g-b--10of12{width:83.333%}.g-b--1of8{width:12.5%}.g-b--3of8{width:37.5%}.g-b--5of8{width:62.5%}.g-b--7of8{width:87.5%}.g-b--1of10{width:10%}.g-b--3of10{width:30%}.g-b--7of10{width:70%}.g-b--9of10{width:90%}.g-b--1of12{width:8.333%}.g-b--5of12{width:41.666%}.g-b--7of12{width:58.333%}.g-b--11of12{width:91.666%}.g-b--push--1of1{margin-left:100%}.g-b--push--1of2,.g-b--push--2of4,.g-b--push--3of6,.g-b--push--4of8,.g-b--push--5of10,.g-b--push--6of12{margin-left:50%}.g-b--push--1of3,.g-b--push--2of6,.g-b--push--4of12{margin-left:33.333%}.g-b--push--2of3,.g-b--push--4of6,.g-b--push--8of12{margin-left:66.666%}.g-b--push--1of4,.g-b--push--2of8,.g-b--push--3of12{margin-left:25%}.g-b--push--3of4,.g-b--push--6of8,.g-b--push--9of12{margin-left:75%}.g-b--push--1of5,.g-b--push--2of10{margin-left:20%}.g-b--push--2of5,.g-b--push--4of10{margin-left:40%}.g-b--push--3of5,.g-b--push--6of10{margin-left:60%}.g-b--push--4of5,.g-b--push--8of10{margin-left:80%}.g-b--push--1of6,.g-b--push--2of12{margin-left:16.666%}.g-b--push--5of6,.g-b--push--10of12{margin-left:83.333%}.g-b--push--1of8{margin-left:12.5%}.g-b--push--3of8{margin-left:37.5%}.g-b--push--5of8{margin-left:62.5%}.g-b--push--7of8{margin-left:87.5%}.g-b--push--1of10{margin-left:10%}.g-b--push--3of10{margin-left:30%}.g-b--push--7of10{margin-left:70%}.g-b--push--9of10{margin-left:90%}.g-b--push--1of12{margin-left:8.333%}.g-b--push--5of12{margin-left:41.666%}.g-b--push--7of12{margin-left:58.333%}.g-b--push--11of12{margin-left:91.666%}.g-b--pull--1of1{margin-right:100%}.g-b--pull--1of2,.g-b--pull--2of4,.g-b--pull--3of6,.g-b--pull--4of8,.g-b--pull--5of10,.g-b--pull--6of12{margin-right:50%}.g-b--pull--1of3,.g-b--pull--2of6,.g-b--pull--4of12{margin-right:33.333%}.g-b--pull--2of3,.g-b--pull--4of6,.g-b--pull--8of12{margin-right:66.666%}.g-b--pull--1of4,.g-b--pull--2of8,.g-b--pull--3of12{margin-right:25%}.g-b--pull--3of4,.g-b--pull--6of8,.g-b--pull--9of12{margin-right:75%}.g-b--pull--1of5,.g-b--pull--2of10{margin-right:20%}.g-b--pull--2of5,.g-b--pull--4of10{margin-right:40%}.g-b--pull--3of5,.g-b--pull--6of10{margin-right:60%}.g-b--pull--4of5,.g-b--pull--8of10{margin-right:80%}.g-b--pull--1of6,.g-b--pull--2of12{margin-right:16.666%}.g-b--pull--5of6,.g-b--pull--10of12{margin-right:83.333%}.g-b--pull--1of8{margin-right:12.5%}.g-b--pull--3of8{margin-right:37.5%}.g-b--pull--5of8{margin-right:62.5%}.g-b--pull--7of8{margin-right:87.5%}.g-b--pull--1of10{margin-right:10%}.g-b--pull--3of10{margin-right:30%}.g-b--pull--7of10{margin-right:70%}.g-b--pull--9of10{margin-right:90%}.g-b--pull--1of12{margin-right:8.333%}.g-b--pull--5of12{margin-right:41.666%}.g-b--pull--7of12{margin-right:58.333%}.g-b--pull--11of12{margin-right:91.666%}.splashscreen{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#373D49;z-index:22}.splashscreen-dillinger{width:260px;height:auto;display:block;margin:0 auto;padding-bottom:3rem}.splashscreen p{font-size:1.25rem;padding-top:.56251rem;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;text-align:center;max-width:500px;margin:0 auto;color:#FFF}.sp-center{position:relative;-webkit-transform:translateY(-50%);transform:translateY(-50%);top:50%}.open-menu>.wrapper{overflow-x:hidden}.page{margin:0 auto;position:relative;top:0;left:0;width:100%;height:100%;z-index:2;-webkit-transition:all .25s ease-in-out;transition:all .25s ease-in-out;background-color:#fff;padding-top:51px;will-change:left}.open-menu .page{left:270px}.icon{display:block;margin:0 auto;width:36px;height:36px;border-radius:3px;text-align:center}.icon svg{display:inline-block;margin-left:auto;margin-right:auto}.icon-preview{background-color:#373D49;line-height:40px}.icon-preview svg{width:19px;height:12px}.icon-settings{background-color:#373D49;line-height:44px}.icon-settings svg{width:18px;height:18px}.icon-link{width:16px;height:16px;line-height:1;margin-right:24px;text-align:right}.navbar{background-color:#373D49;height:51px;width:100%;position:fixed;top:0;left:0;z-index:6;-webkit-transition:all .25s ease-in-out;transition:all .25s ease-in-out;will-change:left}.navbar:after{content:"";display:table;clear:both}.open-menu .navbar{left:270px}.navbar-brand{float:left;margin:0 0 0 24px;padding:0;line-height:42px}.navbar-brand svg{width:85px;height:11px}.nav-left{float:left}.nav-right{float:right}.menu a{border:0;color:#A0AABF;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;outline:none;text-transform:uppercase}.dropdown li,.settings li{line-height:1}.settings{position:fixed;top:67px;right:16px;border-radius:3px;width:288px;background-color:#373D49;padding:16px;z-index:7}.show-settings .settings{display:block}.settings .has-checkbox{float:left}.settings form{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.settings input{width:20%}.settings a{font-size:1.25rem;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;-webkit-font-smoothing:antialiased;line-height:28px;color:#D0D6E2}.settings a:after{content:"";display:table;clear:both}.settings a:hover{color:#35D7BB}.settings li{border-bottom:1px solid #4F535B;margin:0;padding:16px 0}.settings li:last-child{border-bottom:none}.brand{border:none;display:block}.caret{display:inline-block;width:0;height:0;margin-left:6px;vertical-align:middle;position:relative;top:-1px;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.header{border-bottom:1px solid #E8E8E8;position:relative}.words,.characters{line-height:1rem;font-size:.8rem;margin-bottom:.77999rem;padding-top:.22001rem;font-weight:500;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;color:#A0AABF;letter-spacing:1px;text-transform:uppercase;z-index:5;position:absolute;right:16px;top:0}.words span,.characters span{color:#000}.words+.characters{top:22px}.btn{text-align:center;display:inline-block;width:100%;text-transform:uppercase;font-weight:600;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;text-shadow:0 1px 0 #1b8b77;padding:16px 24px;background-color:#35D7BB;border-radius:3px;margin:0 auto 16px;line-height:1;color:#fff;-webkit-transition:all .15s linear;transition:all .15s linear;-webkit-font-smoothing:antialiased}.btn--new,.btn--save{display:block;width:238px}.btn--new:hover,.btn--new:focus,.btn--save:hover,.btn--save:focus{color:#fff;border-bottom-color:transparent;box-shadow:0 1px 3px #24b59c;text-shadow:0 1px 0 #24b59c}.btn--save{background-color:#4A5261;text-shadow:0 1px 1px #1e2127}.btn--save:hover,.btn--save:focus{color:#fff;border-bottom-color:transparent;box-shadow:0 1px 5px #08090a;text-shadow:none}.btn--delete{display:block;width:238px;background-color:transparent;font-size:12px;text-shadow:none}.btn--delete:hover,.btn--delete:focus{color:#fff;border-bottom-color:transparent;text-shadow:0 1px 0 #08090a;opacity:.8}.btn--delete-modal,.btn--ok,.btn--close{border-top:0;background-color:#4A5261;text-shadow:0 1px 0 #08090a;margin:0}.btn--delete-modal:hover,.btn--delete-modal:focus,.btn--ok:hover,.btn--ok:focus,.btn--close:hover,.btn--close:focus{color:#fff;background-color:#292d36;text-shadow:none}.btn--delete-modal{display:inline;width:auto}.overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(55,61,73,.8);-webkit-transition:all .25s ease-in-out;transition:all .25s ease-in-out;-webkit-transition-timing-function:ease-out;transition-timing-function:ease-out;will-change:left,opacity,visibility;z-index:5;opacity:0;visibility:hidden}.show-settings .overlay{visibility:visible;opacity:1}.switch{float:right;line-height:1}.switch input{display:none}.switch small{display:inline-block;cursor:pointer;padding:0 24px 0 0;-webkit-transition:all ease .2s;transition:all ease .2s;background-color:#2B2F36;border-color:#2B2F36}.switch small,.switch small:before{border-radius:30px;box-shadow:inset 0 0 2px 0 #14171F}.switch small:before{display:block;content:'';width:28px;height:28px;background:#fff}.switch.checked small{padding-right:0;padding-left:24px;background-color:#35D7BB;box-shadow:none}.modal--dillinger.about .modal-dialog{font-size:1.25rem;max-width:500px}.modal--dillinger.scope .modal-dialog{max-width:300px;margin:5rem auto}.modal--dillinger .modal-dialog{max-width:600px;width:auto;margin:5rem auto}.modal--dillinger .modal-content{background:#373D49;border-radius:3px;box-shadow:0 2px 5px 0 #2C3B59;color:#fff;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;padding:2rem}.modal--dillinger ul{list-style-type:disc;margin:1rem 0;padding:0 0 0 1rem}.modal--dillinger li{padding:0;margin:0}.modal--dillinger .modal-header{border:0;padding:0}.modal--dillinger .modal-body{padding:0}.modal--dillinger .modal-footer{border:0;padding:0}.modal--dillinger .close{color:#fff;opacity:1}.modal-backdrop{background-color:#373D49}.pagination--dillinger{padding:0!important;margin:1.5rem 0!important;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:stretch;align-content:stretch}.pagination--dillinger,.pagination--dillinger li{display:-webkit-box;display:-ms-flexbox;display:flex}.pagination--dillinger li{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.pagination--dillinger li:first-child>a,.pagination--dillinger li.disabled>a,.pagination--dillinger li.disabled>a:hover,.pagination--dillinger li.disabled>a:focus,.pagination--dillinger li>a{background-color:transparent;border-color:#4F535B;border-right-color:transparent}.pagination--dillinger li.active>a,.pagination--dillinger li.active>a:hover,.pagination--dillinger li.active>a:focus{border-color:#4A5261;background-color:#4A5261;color:#fff}.pagination--dillinger li>a{float:none;color:#fff;width:100%;display:block;text-align:center;margin:0;border-right-color:transparent;padding:6px}.pagination--dillinger li>a:hover,.pagination--dillinger li>a:focus{border-color:#35D7BB;background-color:#35D7BB;color:#fff}.pagination--dillinger li:last-child a{border-color:#4F535B}.pagination--dillinger li:first-child a{border-right-color:transparent}.diNotify{position:absolute;z-index:9999;left:0;right:0;top:0;margin:0 auto;max-width:400px;text-align:center;-webkit-transition:top .5s ease-in-out,opacity .5s ease-in-out;transition:top .5s ease-in-out,opacity .5s ease-in-out;visibility:hidden}.diNotify-body{-webkit-font-smoothing:antialiased;background-color:#35D7BB;background:#666E7F;border-radius:3px;color:#fff;font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;overflow:hidden;padding:1rem 2rem .5rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:baseline;-ms-flex-align:baseline;align-items:baseline;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.diNotify-icon{display:block;width:16px;height:16px;line-height:16px;position:relative;top:3px}.diNotify-message{padding-left:1rem}.zen-wrapper{position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;z-index:10;background-color:#FFF;opacity:0;-webkit-transition:opacity .25s ease-in-out;transition:opacity .25s ease-in-out}.zen-wrapper.on{opacity:1}.enter-zen-mode{background-image:url("../img/icons/enter-zen.svg");right:.5rem;top:.313rem;display:none}.enter-zen-mode,.close-zen-mode{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;background-repeat:no-repeat;width:32px;height:32px;display:block;position:absolute}.close-zen-mode{background-image:url("../img/icons/exit-zen.svg");right:1rem;top:1rem}.zen-page{position:relative;top:0;bottom:0;z-index:11;height:100%;width:100%}#zen{font-size:1.25rem;width:300px;height:80%;margin:0 auto;position:relative;top:10%}#zen:before,#zen:after{content:"";position:absolute;height:10%;width:100%;z-index:12;pointer-events:none}#preview .table{width:auto}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;z-index:99999;display:block}.ui-resizable-e{background-color:#666;border-right:8px solid #e8e8e8;border-left:1px solid #222;width:10px;z-index:88!important;position:relative}.ui-resizable-e:after{content:"-";display:block;position:absolute;top:calc(50% - 16px);left:0;height:25px;width:2px;background-color:rgba(0,0,0,.4);margin:3px}#editor{cursor:ew-resize;position:relative;z-index:auto}.profile-pic{float:left;width:250px}#_default_ a::before{color:#A0AABF}#_default_ img{display:none}#_default_ #_default_{display:block;float:left;max-width:38%;word-wrap:break-word}#_default_ .default-ad{display:none}#_default_ ._default_{display:block}#_default_ a{color:#35d7bb;text-decoration:none}#_default_ a:hover{color:#8ae8d8}#_default_ .default-image{display:none}#_default_ .default-title:after{content:" — "}#_default_ .default-title,#_default_ .default-description{display:inline}#_default_ .default-title{position:relative;font-weight:600;display:none}#_default_ a:before{position:relative;top:0;padding:5px;color:#a0aabf;content:"Ad";text-transform:uppercase;font-size:8px;font-family:Verdana,sans-serif}#_default_{display:block;float:left;max-width:38%;word-wrap:break-word}#_default_ ._default_{display:block;font-size:.75rem;height:51px;letter-spacing:1px;line-height:1rem;padding:18px 24px}body{max-width:1024px;margin:0 auto;overflow:auto;padding:2%}.split{overflow:scroll;padding:0!important}.split-editor{padding-left:0;padding-right:0;position:relative;z-index:3}.show-preview .split-editor{display:none}.split-preview{background-color:#fff;display:none;top:0;position:relative;z-index:4}.show-preview .split-preview{display:block}#editor{font-size:1rem;font-family:"Ubuntu Mono",Monaco;font-weight:400;line-height:2rem;width:100%;height:100%}#editor .ace_gutter{-webkit-font-smoothing:antialiased}.editor-header{width:50%;float:left;border-bottom:1px solid #E8E8E8;position:relative}.editor-header--first{border-right:1px solid #E8E8E8}.preview-html{padding:15px}.preview-html a{color:#A0AABF;text-decoration:underline}.preview-src{white-space:normal}.preview-mode-toggle-src{background-image:url("../img/icons/code.svg")}.preview-mode-toggle-src,.preview-mode-toggle-html{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;background-repeat:no-repeat;width:32px;height:32px;display:block;position:absolute;right:.5rem;top:.5rem;display:none}.preview-mode-toggle-html{background-image:url("../img/icons/eye.svg")}.sr-only{visibility:hidden;text-overflow:110%;overflow:hidden;top:-100px;position:absolute}.mnone{margin:0!important}@media screen and (min-width:27.5em){html{font-size:.875em}ul,ol{margin-bottom:.83999rem;padding-top:.16001rem}p{padding-top:.66001rem}p,pre{margin-bottom:1.33999rem}pre,blockquote p{font-size:1rem;padding-top:.66001rem}blockquote p{margin-bottom:.33999rem}.g{margin-left:-16px;margin-right:-16px}.g-b{padding-left:16px;padding-right:16px}.g-b--m1of1{width:100%}.g-b--m1of2,.g-b--m2of4,.g-b--m3of6,.g-b--m4of8,.g-b--m5of10,.g-b--m6of12{width:50%}.g-b--m1of3,.g-b--m2of6,.g-b--m4of12{width:33.333%}.g-b--m2of3,.g-b--m4of6,.g-b--m8of12{width:66.666%}.g-b--m1of4,.g-b--m2of8,.g-b--m3of12{width:25%}.g-b--m3of4,.g-b--m6of8,.g-b--m9of12{width:75%}.g-b--m1of5,.g-b--m2of10{width:20%}.g-b--m2of5,.g-b--m4of10{width:40%}.g-b--m3of5,.g-b--m6of10{width:60%}.g-b--m4of5,.g-b--m8of10{width:80%}.g-b--m1of6,.g-b--m2of12{width:16.666%}.g-b--m5of6,.g-b--m10of12{width:83.333%}.g-b--m1of8{width:12.5%}.g-b--m3of8{width:37.5%}.g-b--m5of8{width:62.5%}.g-b--m7of8{width:87.5%}.g-b--m1of10{width:10%}.g-b--m3of10{width:30%}.g-b--m7of10{width:70%}.g-b--m9of10{width:90%}.g-b--m1of12{width:8.333%}.g-b--m5of12{width:41.666%}.g-b--m7of12{width:58.333%}.g-b--m11of12{width:91.666%}.g-b--push--m1of1{margin-left:100%}.g-b--push--m1of2,.g-b--push--m2of4,.g-b--push--m3of6,.g-b--push--m4of8,.g-b--push--m5of10,.g-b--push--m6of12{margin-left:50%}.g-b--push--m1of3,.g-b--push--m2of6,.g-b--push--m4of12{margin-left:33.333%}.g-b--push--m2of3,.g-b--push--m4of6,.g-b--push--m8of12{margin-left:66.666%}.g-b--push--m1of4,.g-b--push--m2of8,.g-b--push--m3of12{margin-left:25%}.g-b--push--m3of4,.g-b--push--m6of8,.g-b--push--m9of12{margin-left:75%}.g-b--push--m1of5,.g-b--push--m2of10{margin-left:20%}.g-b--push--m2of5,.g-b--push--m4of10{margin-left:40%}.g-b--push--m3of5,.g-b--push--m6of10{margin-left:60%}.g-b--push--m4of5,.g-b--push--m8of10{margin-left:80%}.g-b--push--m1of6,.g-b--push--m2of12{margin-left:16.666%}.g-b--push--m5of6,.g-b--push--m10of12{margin-left:83.333%}.g-b--push--m1of8{margin-left:12.5%}.g-b--push--m3of8{margin-left:37.5%}.g-b--push--m5of8{margin-left:62.5%}.g-b--push--m7of8{margin-left:87.5%}.g-b--push--m1of10{margin-left:10%}.g-b--push--m3of10{margin-left:30%}.g-b--push--m7of10{margin-left:70%}.g-b--push--m9of10{margin-left:90%}.g-b--push--m1of12{margin-left:8.333%}.g-b--push--m5of12{margin-left:41.666%}.g-b--push--m7of12{margin-left:58.333%}.g-b--push--m11of12{margin-left:91.666%}.g-b--pull--m1of1{margin-right:100%}.g-b--pull--m1of2,.g-b--pull--m2of4,.g-b--pull--m3of6,.g-b--pull--m4of8,.g-b--pull--m5of10,.g-b--pull--m6of12{margin-right:50%}.g-b--pull--m1of3,.g-b--pull--m2of6,.g-b--pull--m4of12{margin-right:33.333%}.g-b--pull--m2of3,.g-b--pull--m4of6,.g-b--pull--m8of12{margin-right:66.666%}.g-b--pull--m1of4,.g-b--pull--m2of8,.g-b--pull--m3of12{margin-right:25%}.g-b--pull--m3of4,.g-b--pull--m6of8,.g-b--pull--m9of12{margin-right:75%}.g-b--pull--m1of5,.g-b--pull--m2of10{margin-right:20%}.g-b--pull--m2of5,.g-b--pull--m4of10{margin-right:40%}.g-b--pull--m3of5,.g-b--pull--m6of10{margin-right:60%}.g-b--pull--m4of5,.g-b--pull--m8of10{margin-right:80%}.g-b--pull--m1of6,.g-b--pull--m2of12{margin-right:16.666%}.g-b--pull--m5of6,.g-b--pull--m10of12{margin-right:83.333%}.g-b--pull--m1of8{margin-right:12.5%}.g-b--pull--m3of8{margin-right:37.5%}.g-b--pull--m5of8{margin-right:62.5%}.g-b--pull--m7of8{margin-right:87.5%}.g-b--pull--m1of10{margin-right:10%}.g-b--pull--m3of10{margin-right:30%}.g-b--pull--m7of10{margin-right:70%}.g-b--pull--m9of10{margin-right:90%}.g-b--pull--m1of12{margin-right:8.333%}.g-b--pull--m5of12{margin-right:41.666%}.g-b--pull--m7of12{margin-right:58.333%}.g-b--pull--m11of12{margin-right:91.666%}.splashscreen p{font-size:1.25rem;margin-bottom:1.43749rem;padding-top:.56251rem}}@media screen and (min-width:46.25em){html{font-size:.875em}ul,ol{margin-bottom:.83999rem;padding-top:.16001rem}p{padding-top:.66001rem}p,pre{margin-bottom:1.33999rem}pre,blockquote p{font-size:1rem;padding-top:.66001rem}blockquote p{margin-bottom:.33999rem}h1{font-size:2.0571429rem;margin-bottom:.21999rem;padding-top:.78001rem}.g{margin-left:-16px;margin-right:-16px}.g-b{padding-left:16px;padding-right:16px}.g-b--t1of1{width:100%}.g-b--t1of2,.g-b--t2of4,.g-b--t3of6,.g-b--t4of8,.g-b--t5of10,.g-b--t6of12{width:50%}.g-b--t1of3,.g-b--t2of6,.g-b--t4of12{width:33.333%}.g-b--t2of3,.g-b--t4of6,.g-b--t8of12{width:66.666%}.g-b--t1of4,.g-b--t2of8,.g-b--t3of12{width:25%}.g-b--t3of4,.g-b--t6of8,.g-b--t9of12{width:75%}.g-b--t1of5,.g-b--t2of10{width:20%}.g-b--t2of5,.g-b--t4of10{width:40%}.g-b--t3of5,.g-b--t6of10{width:60%}.g-b--t4of5,.g-b--t8of10{width:80%}.g-b--t1of6,.g-b--t2of12{width:16.666%}.g-b--t5of6,.g-b--t10of12{width:83.333%}.g-b--t1of8{width:12.5%}.g-b--t3of8{width:37.5%}.g-b--t5of8{width:62.5%}.g-b--t7of8{width:87.5%}.g-b--t1of10{width:10%}.g-b--t3of10{width:30%}.g-b--t7of10{width:70%}.g-b--t9of10{width:90%}.g-b--t1of12{width:8.333%}.g-b--t5of12{width:41.666%}.g-b--t7of12{width:58.333%}.g-b--t11of12{width:91.666%}.g-b--push--t1of1{margin-left:100%}.g-b--push--t1of2,.g-b--push--t2of4,.g-b--push--t3of6,.g-b--push--t4of8,.g-b--push--t5of10,.g-b--push--t6of12{margin-left:50%}.g-b--push--t1of3,.g-b--push--t2of6,.g-b--push--t4of12{margin-left:33.333%}.g-b--push--t2of3,.g-b--push--t4of6,.g-b--push--t8of12{margin-left:66.666%}.g-b--push--t1of4,.g-b--push--t2of8,.g-b--push--t3of12{margin-left:25%}.g-b--push--t3of4,.g-b--push--t6of8,.g-b--push--t9of12{margin-left:75%}.g-b--push--t1of5,.g-b--push--t2of10{margin-left:20%}.g-b--push--t2of5,.g-b--push--t4of10{margin-left:40%}.g-b--push--t3of5,.g-b--push--t6of10{margin-left:60%}.g-b--push--t4of5,.g-b--push--t8of10{margin-left:80%}.g-b--push--t1of6,.g-b--push--t2of12{margin-left:16.666%}.g-b--push--t5of6,.g-b--push--t10of12{margin-left:83.333%}.g-b--push--t1of8{margin-left:12.5%}.g-b--push--t3of8{margin-left:37.5%}.g-b--push--t5of8{margin-left:62.5%}.g-b--push--t7of8{margin-left:87.5%}.g-b--push--t1of10{margin-left:10%}.g-b--push--t3of10{margin-left:30%}.g-b--push--t7of10{margin-left:70%}.g-b--push--t9of10{margin-left:90%}.g-b--push--t1of12{margin-left:8.333%}.g-b--push--t5of12{margin-left:41.666%}.g-b--push--t7of12{margin-left:58.333%}.g-b--push--t11of12{margin-left:91.666%}.g-b--pull--t1of1{margin-right:100%}.g-b--pull--t1of2,.g-b--pull--t2of4,.g-b--pull--t3of6,.g-b--pull--t4of8,.g-b--pull--t5of10,.g-b--pull--t6of12{margin-right:50%}.g-b--pull--t1of3,.g-b--pull--t2of6,.g-b--pull--t4of12{margin-right:33.333%}.g-b--pull--t2of3,.g-b--pull--t4of6,.g-b--pull--t8of12{margin-right:66.666%}.g-b--pull--t1of4,.g-b--pull--t2of8,.g-b--pull--t3of12{margin-right:25%}.g-b--pull--t3of4,.g-b--pull--t6of8,.g-b--pull--t9of12{margin-right:75%}.g-b--pull--t1of5,.g-b--pull--t2of10{margin-right:20%}.g-b--pull--t2of5,.g-b--pull--t4of10{margin-right:40%}.g-b--pull--t3of5,.g-b--pull--t6of10{margin-right:60%}.g-b--pull--t4of5,.g-b--pull--t8of10{margin-right:80%}.g-b--pull--t1of6,.g-b--pull--t2of12{margin-right:16.666%}.g-b--pull--t5of6,.g-b--pull--t10of12{margin-right:83.333%}.g-b--pull--t1of8{margin-right:12.5%}.g-b--pull--t3of8{margin-right:37.5%}.g-b--pull--t5of8{margin-right:62.5%}.g-b--pull--t7of8{margin-right:87.5%}.g-b--pull--t1of10{margin-right:10%}.g-b--pull--t3of10{margin-right:30%}.g-b--pull--t7of10{margin-right:70%}.g-b--pull--t9of10{margin-right:90%}.g-b--pull--t1of12{margin-right:8.333%}.g-b--pull--t5of12{margin-right:41.666%}.g-b--pull--t7of12{margin-right:58.333%}.g-b--pull--t11of12{margin-right:91.666%}.splashscreen-dillinger{width:500px}.splashscreen p{font-size:1.25rem;margin-bottom:1.43749rem;padding-top:.56251rem}.enter-zen-mode{display:block}.close-zen-mode{right:3rem;top:3rem}#zen{font-size:1.25rem;width:500px}.split-editor{border-right:1px solid #E8E8E8;float:left;height:calc(100vh - 172px);-webkit-overflow-scrolling:touch;padding-right:16px;width:50%}.show-preview .split-editor{display:block}.split-preview{display:block;float:right;height:calc(100vh - 172px);-webkit-overflow-scrolling:touch;position:relative;top:0;width:50%}#editor{font-size:1rem}.preview-mode-toggle-src,.preview-mode-toggle-html{display:block}}@media screen and (min-width:62.5em){html{font-size:.875em}ul,ol{margin-bottom:.83999rem;padding-top:.16001rem}p{padding-top:.66001rem}p,pre{margin-bottom:1.33999rem}pre,blockquote p{font-size:1rem;padding-top:.66001rem}blockquote p{margin-bottom:.33999rem}h1{font-size:2.0571429rem;margin-bottom:.21999rem;padding-top:.78001rem}.g{margin-left:-16px;margin-right:-16px}.g-b{padding-left:16px;padding-right:16px}.g-b--d1of1{width:100%}.g-b--d1of2,.g-b--d2of4,.g-b--d3of6,.g-b--d4of8,.g-b--d5of10,.g-b--d6of12{width:50%}.g-b--d1of3,.g-b--d2of6,.g-b--d4of12{width:33.333%}.g-b--d2of3,.g-b--d4of6,.g-b--d8of12{width:66.666%}.g-b--d1of4,.g-b--d2of8,.g-b--d3of12{width:25%}.g-b--d3of4,.g-b--d6of8,.g-b--d9of12{width:75%}.g-b--d1of5,.g-b--d2of10{width:20%}.g-b--d2of5,.g-b--d4of10{width:40%}.g-b--d3of5,.g-b--d6of10{width:60%}.g-b--d4of5,.g-b--d8of10{width:80%}.g-b--d1of6,.g-b--d2of12{width:16.666%}.g-b--d5of6,.g-b--d10of12{width:83.333%}.g-b--d1of8{width:12.5%}.g-b--d3of8{width:37.5%}.g-b--d5of8{width:62.5%}.g-b--d7of8{width:87.5%}.g-b--d1of10{width:10%}.g-b--d3of10{width:30%}.g-b--d7of10{width:70%}.g-b--d9of10{width:90%}.g-b--d1of12{width:8.333%}.g-b--d5of12{width:41.666%}.g-b--d7of12{width:58.333%}.g-b--d11of12{width:91.666%}.g-b--push--d1of1{margin-left:100%}.g-b--push--d1of2,.g-b--push--d2of4,.g-b--push--d3of6,.g-b--push--d4of8,.g-b--push--d5of10,.g-b--push--d6of12{margin-left:50%}.g-b--push--d1of3,.g-b--push--d2of6,.g-b--push--d4of12{margin-left:33.333%}.g-b--push--d2of3,.g-b--push--d4of6,.g-b--push--d8of12{margin-left:66.666%}.g-b--push--d1of4,.g-b--push--d2of8,.g-b--push--d3of12{margin-left:25%}.g-b--push--d3of4,.g-b--push--d6of8,.g-b--push--d9of12{margin-left:75%}.g-b--push--d1of5,.g-b--push--d2of10{margin-left:20%}.g-b--push--d2of5,.g-b--push--d4of10{margin-left:40%}.g-b--push--d3of5,.g-b--push--d6of10{margin-left:60%}.g-b--push--d4of5,.g-b--push--d8of10{margin-left:80%}.g-b--push--d1of6,.g-b--push--d2of12{margin-left:16.666%}.g-b--push--d5of6,.g-b--push--d10of12{margin-left:83.333%}.g-b--push--d1of8{margin-left:12.5%}.g-b--push--d3of8{margin-left:37.5%}.g-b--push--d5of8{margin-left:62.5%}.g-b--push--d7of8{margin-left:87.5%}.g-b--push--d1of10{margin-left:10%}.g-b--push--d3of10{margin-left:30%}.g-b--push--d7of10{margin-left:70%}.g-b--push--d9of10{margin-left:90%}.g-b--push--d1of12{margin-left:8.333%}.g-b--push--d5of12{margin-left:41.666%}.g-b--push--d7of12{margin-left:58.333%}.g-b--push--d11of12{margin-left:91.666%}.g-b--pull--d1of1{margin-right:100%}.g-b--pull--d1of2,.g-b--pull--d2of4,.g-b--pull--d3of6,.g-b--pull--d4of8,.g-b--pull--d5of10,.g-b--pull--d6of12{margin-right:50%}.g-b--pull--d1of3,.g-b--pull--d2of6,.g-b--pull--d4of12{margin-right:33.333%}.g-b--pull--d2of3,.g-b--pull--d4of6,.g-b--pull--d8of12{margin-right:66.666%}.g-b--pull--d1of4,.g-b--pull--d2of8,.g-b--pull--d3of12{margin-right:25%}.g-b--pull--d3of4,.g-b--pull--d6of8,.g-b--pull--d9of12{margin-right:75%}.g-b--pull--d1of5,.g-b--pull--d2of10{margin-right:20%}.g-b--pull--d2of5,.g-b--pull--d4of10{margin-right:40%}.g-b--pull--d3of5,.g-b--pull--d6of10{margin-right:60%}.g-b--pull--d4of5,.g-b--pull--d8of10{margin-right:80%}.g-b--pull--d1of6,.g-b--pull--d2of12{margin-right:16.666%}.g-b--pull--d5of6,.g-b--pull--d10of12{margin-right:83.333%}.g-b--pull--d1of8{margin-right:12.5%}.g-b--pull--d3of8{margin-right:37.5%}.g-b--pull--d5of8{margin-right:62.5%}.g-b--pull--d7of8{margin-right:87.5%}.g-b--pull--d1of10{margin-right:10%}.g-b--pull--d3of10{margin-right:30%}.g-b--pull--d7of10{margin-right:70%}.g-b--pull--d9of10{margin-right:90%}.g-b--pull--d1of12{margin-right:8.333%}.g-b--pull--d5of12{margin-right:41.666%}.g-b--pull--d7of12{margin-right:58.333%}.g-b--pull--d11of12{margin-right:91.666%}.splashscreen-dillinger{width:700px}.splashscreen p{font-size:1.25rem;margin-bottom:1.43749rem;padding-top:.56251rem}}@media screen and (min-width:87.5em){html{font-size:.875em}ul,ol{margin-bottom:.83999rem;padding-top:.16001rem}p{padding-top:.66001rem}p,pre{margin-bottom:1.33999rem}pre,blockquote p{font-size:1rem;padding-top:.66001rem}blockquote p{margin-bottom:.33999rem}h1{font-size:2.0571429rem;margin-bottom:.21999rem;padding-top:.78001rem}.splashscreen-dillinger{width:800px}.splashscreen p{font-size:1.25rem;margin-bottom:1.43749rem;padding-top:.56251rem}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}@media screen and (max-width:720px){#_default_{max-width:60%}#_default_ ._default_{font-size:.75rem;line-height:1rem;padding:12px 24px}}@media screen and (max-width:620px){#_default_{max-width:50%}#_default_ ._default_{font-size:.66rem;letter-spacing:1px;line-height:1rem;padding:10px 24px}}@media screen and (max-width:520px){#_default_ ._default_{font-size:.4rem;line-height:.875rem;padding:6px 12px 6px 24px;text-align:justify}}@media screen and (max-width:460px){#_default_{display:none}}@media screen and (max-width:46.1875em){.editor-header{display:none}.editor-header--first{display:block;width:100%}}</style><br />
For years people have been wondering why and when Philips would allow users to customise startup behaviour after a power cut. No more! Philips has recently updated the firmware of the bridge and bulbs to allow for a custom power-on behaviour. Unfortunately for now it seems to allow only color temperature (whites) and brightness. But it’s better than nothing!<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXqPp8urrnZTukyx0vdxQqtPJrcPL2030Z4m6_WyAJ57_oybsb7KFPDmSNq6JaX-LqgU3b8KRnucFvW-fQYquvyCKlAlEfFoSFuAavfa7myDj-ECIY_Qg8D5G9UKjV3PHwIaEUBFFgal2y/s1600/DSC_0170.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1144" data-original-width="1600" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXqPp8urrnZTukyx0vdxQqtPJrcPL2030Z4m6_WyAJ57_oybsb7KFPDmSNq6JaX-LqgU3b8KRnucFvW-fQYquvyCKlAlEfFoSFuAavfa7myDj-ECIY_Qg8D5G9UKjV3PHwIaEUBFFgal2y/s400/DSC_0170.jpg" width="400" /></a></div><br />
<h3><a href="https://www.blogger.com/null" id="Open_the_bridge_debug_page_2"></a>Open the bridge debug page</h3><ul><li>Open a browser (preferably on a PC or Mac)</li>
<li>Go to <code>https://discovery.meethue.com</code> to see the IP address of your Hue bridge (it is called <code>internalipaddress</code>). In my case it is <code>192.168.1.32</code></li>
<li>Open your favourite browser and enter <code>http://192.168.1.32/debug/clip.html</code> replacing my IP address with the IP you found in the previous step.<br />
<br />
You should see the following page:</li>
</ul><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMhD44TddHoW1TuOWXsmANTpQYBWmW4r_IzvmBsO4YMNSEfhXt7Jif1ED7csi1sYnW9zbIBARucgDY8pxC0crBHt0iQCh1lVdA6WSsGRF1DZLOX7xWK_YthQd5dg2VL8PxZOBbayykzU2R/s1600/Screen+Shot+2018-12-06+at+18.22.48.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="568" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMhD44TddHoW1TuOWXsmANTpQYBWmW4r_IzvmBsO4YMNSEfhXt7Jif1ED7csi1sYnW9zbIBARucgDY8pxC0crBHt0iQCh1lVdA6WSsGRF1DZLOX7xWK_YthQd5dg2VL8PxZOBbayykzU2R/s320/Screen+Shot+2018-12-06+at+18.22.48.png" width="277" /></a></div><div><br />
</div><h3><a href="https://www.blogger.com/null" id="Get_an_API_key_8"></a>Get an API key</h3>If you don’t have an API key yet you can do the following:<br />
<ul><li>Replace the default value (<code>/api/1234</code>) with <code>/api</code></li>
<li>Paste the following content in the ‘message body’ field: <code>{"devicetype": "debug_credential" }</code></li>
<li>Press the ‘POST’-button on the web page</li>
<li>Run to your Hue Bridge and press the round button on it</li>
<li>Press the ‘POST’-button on the web page again</li>
<li>Copy the value for “username” to some text editor so you won’t lose it. This value represents your API key.</li>
</ul><h3><a href="https://www.blogger.com/null" id="Identify_the_lights_to_modify_17"></a>Identify the lights to modify</h3>In the URL field of the debug page you can append your username, for example /api/0123456789012345678901234567 if your api key is 0123456789012345678901234567.<br />
<br />
Next you can get a list of lights by appending /lights to the URL. Then you can press the GET button.<br />
<br />
Every light that allows custom startup behaviour will have a <code>startup</code> key in the <code>config</code> property (see image below).<br />
<br />
Write down all the ID’s of the lights that you want to modify and that allow custom startup behaviour.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggWnEsKXINMfDabB9lxY-KQfD76DZWedkbZjNC9V1ON-HD3PtN-DAKDXflq4yDdD_BbmlWdFo_MP5E-ar1RO-hAl3d5i38HaCelyz4Y23hWMjYQ62hsBwpsoPEMKDXEWeZcrJjJ0O_rQU7/s1600/Screen+Shot+2018-12-06+at+18.34.16.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="462" data-original-width="524" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggWnEsKXINMfDabB9lxY-KQfD76DZWedkbZjNC9V1ON-HD3PtN-DAKDXflq4yDdD_BbmlWdFo_MP5E-ar1RO-hAl3d5i38HaCelyz4Y23hWMjYQ62hsBwpsoPEMKDXEWeZcrJjJ0O_rQU7/s320/Screen+Shot+2018-12-06+at+18.34.16.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-size: small; text-align: start;">Example showing that the light with ID </span><code style="text-align: start;">1</code><span style="font-size: small; text-align: start;"> allows custom startup configuration. You can also see </span><code style="text-align: start;">2</code><span style="font-size: small; text-align: start;">, which shows the ID of the second light in the response.</span></td></tr>
</tbody></table><br />
<h3><a href="https://www.blogger.com/null" id="Modify_the_lights_26"></a>Modify the lights</h3>Append the ID of the light you want to customise to the URL. As a sanity check, press the GET-button and verify that you get the status of the light in the response (no errors).<br />
<br />
Paste the following in the Message Body field:<br />
<pre><code class="language-|json">{
"config": {
"startup": {
"mode": "custom",
"customsettings": {
"bri": 254,
"ct": 500
}
}
}
}
</code></pre><ul><li>Adjust the <code>Bri</code> (Brightness, 0-255) and <code>CT</code> (Colour Temperature, ranging from 153 (6500 Kelvin, bright white) to 500 (2000 Kelvin, warm white).</li>
<li>Press the PUT button</li>
<li>Repeat for the other lights</li>
</ul>Now to verify that it works, turn off the physical power switch to your light, wait for approx 5 seconds, and flip the switch again. Enjoy!Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-31096852859369703652017-07-16T14:08:00.004+02:002020-12-02T14:48:03.897+01:00HP Microserver Gen8 + i3 2120: does it ECC?So the interwebs does a lot of claims about whether the <i>Sandy Bridge</i> generation i3's support ECC memory. For example <a href="https://communities.intel.com/thread/60807">here</a>, <a href="https://arstechnica.com/civis/viewtopic.php?p=22587440">here</a> and <a href="https://en.wikipedia.org/wiki/List_of_Intel_Core_i3_microprocessors#.22Sandy_Bridge.22_.2832_nm.29_2">here</a>. Intel ARK <a href="http://ark.intel.com/products/53426/Intel-Core-i3-2120-Processor-3M-Cache-3_30-GHz">does not show</a> any information that mentions ECC support for the i3-2120.<br />
<br />
Now as some of you have read, <a href="http://blog.thisiswhytheinternetexists.com/2016/11/the-hp-microserver-gen8-for-eur-200-is.html">I've purchased an HP Microserver Gen8 with a Celeron G1610T</a> inside which does support ECC. I purchased a second-hand Intel Core i3-2120 but as soon as it arrived my colleague said "well that's lame, it doesn't support ECC". I researched the internet and came to a sad conclusion. There seemed to be no official support for ECC. Why risk ruining a "production" server with a non-ECC capable CPU? So the CPU disappeared in my desk.<br />
<br />
<h3>
A few months later</h3>
I re-did some of my research and realised that HP <a href="https://www.hpe.com/h20195/v2/default.aspx?cc=uk&lc=en&oid=1008690022">did offer the Microserver with i3 processors</a> from the Sandy Bridge generation. This meant that the hardware should be capable and knowing that most of the cpu's from a certain family probably are from the same wafers it wouldn't be too far fetched to assume that most (if not: all) of the chips from the same series should be able to support ECC.<br />
<br />
<h3>
Long story short</h3>
<div>
I'm running the i3-2120 now in the Microserver Gen8 and it works <b>perfectly</b>. ECC is shown as enabled in both the iLO and unRaid. No issues whatsoever. An i3 CPU of this generation can be found second hand between 25 and 45 euro's (approx.). And don't worry about the TDP except if you're hammering the system 24/7. My temperatures haven't gone up at all :). So I can recommend this upgrade to anyone wanting to get some more <i>oomph</i> from their Microserver Gen8 with a G1610T in it (<a href="http://blog.thisiswhytheinternetexists.com/2016/11/the-hp-microserver-gen8-for-eur-200-is.html">which is a great deal on it's own!</a>). </div>
Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-69133402985782723492016-11-20T15:59:00.003+01:002016-11-20T15:59:48.329+01:00LEDE project: prevent having to re-flash the latest nightly build every time you need a new package<div class="separator" style="clear: both; text-align: center;">
<a href="https://avatars3.githubusercontent.com/u/18146401" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://avatars3.githubusercontent.com/u/18146401" /></a></div>
I really admire the <a href="https://www.lede-project.org/" target="_blank">LEDE project</a> and the <a href="https://www.lede-project.org/about.html" target="_blank">reasons why they decided that it was necessary to fork openwrt and continue in a way that they saw fit</a>. Unfortunately as they only recently started (somewhere about May 2016) there are no official releases yet and this means that there are only <a href="https://www.lede-project.org/downloads.html" target="_blank">nightly builds</a>.<div>
<br /></div>
<div>
This 'guide' will work for both openwrt and lede nightly builds. The reason is that every night the packages and dependencies get rebuilt and packages that rely on a specific kernel/kernel module version can not be installed at a later moment (when the new nightly build replaces the previous one online). To solve this we can make a copy of all packages for a given nightly build. In a nutshell:</div>
<div>
<br /></div>
<div>
<ol>
<li>Download the firmware file from the LEDE/openwrt site</li>
<li>Run the commands that download all packages from the LEDE/openwrt site</li>
<li>Install/upgrade to recent build</li>
<li>Run a local webserver</li>
<li>Modify the package repository URL's to match your local webserver</li>
</ol>
</div>
<div>
<br /></div>
<div>
So lets get started!</div>
<div>
<br /></div>
<h3>
Download the firmware file</h3>
<div>
This is easy and probably something you've done before. If not: check out the architecture of your router and try to find whether openwrt/LEDE already supports your router. If they don't you're out of luck for now. For this guide I'll be using the TP-Link Archer C7 which is contained in the ar71xx builds of both LEDE and openwrt. </div>
<div>
<br /></div>
<h3>
Run these commands that download all packages from the LEDE/openwrt site</h3>
<div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">wget -m --no-parent -e robots=off https://downloads.lede-project.org/snapshots/targets/ar71xx/generic/packages/</span></div>
</div>
<div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">wget -m --no-parent -e robots=off http://downloads.lede-project.org/snapshots/packages/mips_24kc/base</span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"></span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">wget -m --no-parent -e robots=off http://downloads.lede-project.org/snapshots/packages/mips_24kc/luci</span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"></span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">wget -m --no-parent -e robots=off http://downloads.lede-project.org/snapshots/packages/mips_24kc/packages</span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"></span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">wget -m --no-parent -e robots=off http://downloads.lede-project.org/snapshots/packages/mips_24kc/routing</span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"></span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">wget -m --no-parent -e robots=off http://downloads.lede-project.org/snapshots/packages/mips_24kc/telephony</span></div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"></span></div>
<br />
The commands above should download all the packages that LEDE references within it's "software distribution feeds". For openwrt all references to lede-project.org should be replaced with openwrt.org. If you already have a version of openwrt/LEDE installed you can just make sure that you wget every of the URL's in the list instead of the URL's I provided above. Checkout 'System > Software' => Configuration tab for a list of feeds used by the current firmware.<br />
<br />
After downloading the feeds you might want to move the contents of the downloads.lede-project.org/snapshots folder to a new folder. I'm using /Users/flix/Documens/lede-snapshots here as the /Users folder can be shared with Docker containers by default if you're using macOS. Not sure about how permissive Linux is in this regard.<br />
<br />
<h3>
Install/upgrade to the downloaded build</h3>
<div>
After downloading the packages you can install the firmware. To be sure that your 'offline' package feeds actually will work I suggest not (re)installing any of your packages just yet. Just the firmware.</div>
<div>
<br /></div>
<h3>
Run a local webserver</h3>
</div>
<div>
Of course, the goal of downloading the packages is to serve them at a later moment in time. Let's get it started:</div>
<div>
<br /></div>
<div>
<div style="background-color: rgba(255, 48, 150, 0.85098); color: #f4f4f4; font-family: Monaco; font-size: 10px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">docker run --name nginx -v /Users/flix/Documents/lede-snapshots:/usr/share/nginx/html:ro -d -p 8080:80 nginx</span></div>
<br />
The above command will pull an nginx container from docker hub and tell it to serve your local folder (containing the packages) on port 8080 from the machine you're running on. Of course you can copy the files to your home server, NAS, raspberry pi or any other device that can run a web server permanently, but for my use case (occasional desire to try out a package) I find spinning up a docker container the easiest.<br />
<br />
<h3>
Modify the package feed URLs</h3>
</div>
<div>
So now we can just swap the downloads.lede-project.org/snapshots part with the IP address of our webserver. This is it! You can now install packages from your local package mirror! Good luck!</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTyzPy9tLgEvUDRwiGorUdgCSaOqPXMegsu-r3dvxHpBDMAX2UAU6Y25ozSJnKb41HVSgqOuIy_2aN4y-79QnbCUvdMkURHkN_Ol1fzDoukfySfT0oVuEpMzN75BaeIifQaneiUsUmUALJ/s1600/Screen+Shot+2016-11-20+at+15.43.32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="" border="0" height="170" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTyzPy9tLgEvUDRwiGorUdgCSaOqPXMegsu-r3dvxHpBDMAX2UAU6Y25ozSJnKb41HVSgqOuIy_2aN4y-79QnbCUvdMkURHkN_Ol1fzDoukfySfT0oVuEpMzN75BaeIifQaneiUsUmUALJ/s400/Screen+Shot+2016-11-20+at+15.43.32.png" title="The list of entries in the Distribution Feeds field" width="400" /></a></div>
<div>
<br /></div>
Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-42145963954472764522016-11-07T06:30:00.000+01:002016-11-07T06:30:16.733+01:00The HP Microserver Gen8 for EUR 200. Is it worth it?So recently our Drobo at QwikSense (my other company) died. Which wasn't really a problem, except that it was storing our Time Machine backups for my computer and my colleagues' MacBooks. So I was looking for a reliable storage solution with room to spare for an extra disk and preferably with ECC memory.<br />
<br />
In the NAS world you're either out of luck if you're looking for something at around €200. Most of the time this will give you an ARM device with HDD-slots. On top of that this locks you into the vendor firmware (and support) and most of the time building something yourself with the provided kernel/firmware sources is not enough to build a robust solution that gives you a 'simple' user interface that just does what it should.<br />
<br />
Of course we could build something ourselves. Whack a Mini-ITX board in a dito casing and voilà: hard disks attached to your network. But I don't have the time to do this and the number of Mini-ITX boards that sports an ECC-capable CPU/RAM at a reasonable price is close to zero.<br />
<br />
<h3>
Our saviour</h3>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyxknCIbPQRBEtfDi9ZU-QaAlbIezDTN4vD42Ge-BEbeSRfq-UGAPGVRiT4iAS_9Z3aHGZOsPKhJMJ54YWJt9X2JqCD8TjCLc2noPBlY9cz-AOSbITXDW-orz6VJsd4U0Y4AwOsP6GDecQ/s1600/open.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiyxknCIbPQRBEtfDi9ZU-QaAlbIezDTN4vD42Ge-BEbeSRfq-UGAPGVRiT4iAS_9Z3aHGZOsPKhJMJ54YWJt9X2JqCD8TjCLc2noPBlY9cz-AOSbITXDW-orz6VJsd4U0Y4AwOsP6GDecQ/s320/open.jpg" width="320" /></a>Enter the HP Gen8 Microserver. The model with a <a href="http://ark.intel.com/products/71074/Intel-Celeron-Processor-G1610T-2M-Cache-2_30-GHz" target="_blank">Celeron G1610T</a> and 4GB ECC(!) RAM <a href="https://tweakers.net/pricewatch/463569/hp-proliant-microserver-gen8-g1610t.html" target="_blank">can currently be purchased in the Netherlands for €203 euros</a> at the cheapest reliable internet store at the time of writing! Now the strange (and awesome) thing about this tiny server is that it has a <a href="http://ark.intel.com/products/71074/Intel-Celeron-Processor-G1610T-2M-Cache-2_30-GHz" target="_blank">CPU</a>, memory and a motherboard that support ECC! Can you believe it? And as an extra, HP's ILO4 management solution is also present. You can actually turn this thing on remotely if it's switched off. You can forcefully reboot it if the kernel crashes. It has features that "real" servers have, but in a tiny and silent package that looks AWESOME.<br />
<br />
Note that the image above was ripped from 3dnews.ru. Also note that this is not the exact same model that you can get for such a low price. My model did not come with an optical drive, but who needs that anyway?<br />
<br />
<h3>
Current setup</h3>
We still had some drives from the Drobo, so we put those in and added a 128GB SSD from Plextor to act as a caching drive. This confirmed my suspicion that the Drobo was in fact dead as a dodo. The drives were all okay! Because some of the drives that were used in the Drobo were WD Greens (and everybody is always crying about how WD Greens drop out of RAID arrays) I decided to WDIDLE3 them. The easiest way for me was to get <a href="http://www.ultimatebootcd.com/download.html" target="_blank">UBCD</a>, <a href="http://wiki.ultimatebootcd.com/?title=Tutorials:USB_Installation" target="_blank">put it on a USB drive</a> and boot the Microserver from that. Now I must stress that you should NOT connect ANY other drives than the ONE drive you want to flash (except for USB disks of course, they don't count). When booting from de USB drive, open "Disk Management" or something similar (sorry, I forgot what it actually was) and then select WDIDLE3 at the bottom of the list of tools. You might get a list with a lot of choices and a countdown. Let the countdown pass and wait for a DOS-like prompt. At the prompt enter the following command:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">WDIDLE3.exe /s300</span> (for 5 minutes).<br />
<br />
That's it. Power down the system and repeat for any WD Green drives you have lying around. Unraid time!<br />
<br />
<h3>
Unraid</h3>
<div>
Since I saw <a href="https://www.youtube.com/watch?v=LXOaCkbt4lI" target="_blank">LinusTechTips' 7 Gamers 1 CPU</a> build I was very interested in <a href="https://lime-technology.com/" target="_blank">unRaid</a> as a storage solution. While I'm still running my <a href="http://www.smallnetbuilder.com/nas/nas-reviews/31272-netgear-readynas-ultra-4-reviewed" target="_blank">Netgear ReadyNAS 4 Ultra</a> at home (<a href="https://community.netgear.com/t5/Using-your-ReadyNAS/OS6-now-works-on-x86-Legacy-WARNING-NO-NTGR-SUPPORT/td-p/897021" target="_blank">running ReadyNAS OS6</a> while Netgear only provided updates on OS4) I have wanted to own a machine like this. Docker on the ReadyNAS wouldn't work (because I believe the kernel was too old, not sure if that is still the case since they migrated to Jessie in the latest firmware update) but on unRaid the sky is the limit as VM's, Docker and plugins can all be used out of the box. There is a very active community providing solutions to run Plex Media Server, Resilio Sync, CouchPotato, SabNZBD and many more tools for media management. As we use Resilio Sync at work I decided to install that. </div>
<div>
<br /></div>
<div>
Note that the basic license for unRaid allows a maximum of 6 internal drives (== SATA) while the MicroServer only has 5 SATA ports (the fifth port is for the optical drive). The USB drive does not count towards the number of drives. Unless you're planning on adding a SAS card and an external storage enclosure you'll be fine with a basic license. And if you're not, you probably weren't planning on keeping the budget low anyway.</div>
<div>
<br /></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="clear: left; float: right; margin-bottom: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1h8LlJ4d5O0eHKYViFPGyZbyYU33MME_RvJ-4X-gj2YUTtkyagTVFsGxltFExDLD5BtyV2TWk3aSN3H15ixqODnvyA6FJp3fCACc1b6zvqBG50OAHVPBqtlRa6SWPcqkSea3CSbBPv_9w/s1600/1zYGjm2v1PSb9Nq.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1h8LlJ4d5O0eHKYViFPGyZbyYU33MME_RvJ-4X-gj2YUTtkyagTVFsGxltFExDLD5BtyV2TWk3aSN3H15ixqODnvyA6FJp3fCACc1b6zvqBG50OAHVPBqtlRa6SWPcqkSea3CSbBPv_9w/s320/1zYGjm2v1PSb9Nq.jpg" width="207" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Photo from a <a href="https://tweakers.net/productreview/108203/hp-proliant-microserver-gen8-g1610t.html" target="_blank">review on tweakers.net</a><br />(dutch)</td></tr>
</tbody></table>
<h3>
Power consumption</h3>
<div>
While I've read different thing about the Gen8 Micro I've not been able to measure the power consumption yet. Hopefully I'll be able to report on that soon.</div>
<div>
<br /></div>
<h3>
Upgrades (and potential for win)</h3>
<div>
The Gen8 Microserver has a regular desktop-formfactor Intel CPU on board in socket 1155. While the CPU has a TDP of just 35 watts, many people have <a href="https://b3n.org/installed-xeon-e3-1230v2-in-gen8-hp-microserver/" target="_blank">retrofitted their Gen8 with beefier CPU's</a>. This is one of the cheapest ways to create a powerful, compact and mostly silent reliable server for a small company or for media streaming. Especially if you have a few drives lying around, this project (including CPU upgrade, SSD cache disk and unRaid license but excluding HDD's) would set you back around €420. Sounds like a sweet deal to me! But even without the CPU upgrade it's a great deal. Let me know what you think!</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-9411311066037076942016-08-21T12:43:00.000+02:002016-08-21T13:13:36.717+02:00Energy measurement with Domoticz and Grafana. Yes, it's easy!A while ago I started tracking the power and gas consumption at home. To do this I read the meters every sunday afternoon and this gave me some insight in the power consumption. Unfortunately this also means that you have the measurement resolution of a week, so you can't really change your habits and see the effect on power/gas consumption.<br />
<br />
<a name='more'></a><br />
Because I've already set my thermostat to it's most eco-friendly settings (water pump set to slowest, comfort mode off and a reasonably low temperature) and it's summer now anyway I decided to focus on power. In the Netherlands you can purchase a rebranded <a href="http://northq.com/electricitystarterkit/" target="_blank">NorthQ NQ-92021</a> Z-Wave power monitoring device, which is called the <a href="https://tweakers.net/pricewatch/314280/e-domotica-energy-reader-(stand-alone-set-met-z-wave-usb-stick).html" target="_blank">Eminent EM6600 Energy Reader Set</a>. The set consists of a Z-Wave box with a connector for a sensor that you <a href="https://www.youtube.com/watch?v=UICEpJ46oCc" target="_blank">stick on your power meter</a> and a USB Z-Wave transceiver. To be honest at this price point it's an <i>absolute steal</i> compared to most Z-Wave hardware<i>. </i>It works on meters with an LED as well as meters with a spinning disc.<br />
<br />
While the hardware is awesome considering its price tag the software is built in Adobe Air and is only released for Windows. While it is possible to do setup without the software I decided the easier route would be to just start a VM with Windows and do the <a href="http://www.e-domotica.com/uploaded/downloads/em6600-uk.pdf" target="_blank">setup, pairing and calibration with the provided software</a>.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhlkpUBpYqFgVYRh_q1uDmxGTed8gVrNTRRx4mfrDLDQVIzyLHqsrYm0YU606bhlIgNA14LAn5Cp4PL5HSfBNzXj9D8P6BDkaxUrMqxWgvQU9vAyAptWh1Z3przQgRIKIwsbCPji02Ka02/s1600/Screen+Shot+2016-08-21+at+11.54.36.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhlkpUBpYqFgVYRh_q1uDmxGTed8gVrNTRRx4mfrDLDQVIzyLHqsrYm0YU606bhlIgNA14LAn5Cp4PL5HSfBNzXj9D8P6BDkaxUrMqxWgvQU9vAyAptWh1Z3przQgRIKIwsbCPji02Ka02/s200/Screen+Shot+2016-08-21+at+11.54.36.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">List of my hardware in Domoticz: <br />
the OpenZWave device is at the top <br />
of the list.</td></tr>
</tbody></table>
After pairing the EM6600 meter and installing it (see the software application for this, every step is explained) you can remove the USB stick from your PC and attach it to your Pi. In Domoticz go to Setup > Hardware and add a device of type <i>OpenZWave USB</i>. You can see what the entry should look like <br />
here (it's at the top of the list).<br />
<br />
When you open the Setup for the OpenZWave USB you should already see the EnergyMeter device in the list. Note that every change you make to the EnergyMeter will take up to 15 minutes to process and apparently operations are queued. By sending a lot of commands I delayed receiving data. So just <b>be patient</b> and wait for data! If it doesn't work after waiting for 30 minutes or so, fiddle around, but keep the number of changes to a minimum to prevent even more delay.<br />
<br />
<h3>
So you've got data. Now what?</h3>
After fiddling with Domoticz to see some actual data I decided I wanted more. The resolution of the data displayed within Domoticz is low (1h when viewing data per day) but I have been writing incoming data to InfluxDB for some time now. I wanted Grafana on my Pi! I had a look on the interwebs only to find that apparently the Raspberry Pi B is not supported by <a href="https://github.com/fg2it/grafana-on-raspberry" target="_blank">most</a> <a href="http://raspberrypi.stackexchange.com/questions/37967/how-to-install-influxdb-and-grafana" target="_blank">of</a> <a href="https://forum.mysensors.org/topic/3183/influxdb-and-grafana-on-raspberrypi/4" target="_blank">the</a> <a href="http://giatro.me/2015/09/30/install-influxdb-and-grafana-on-raspberry-pi.html" target="_blank">arm/pi</a> <a href="https://github.com/heziegl/rpi-grafana" target="_blank">guides</a> for installing Grafana. I decided to go with <a href="https://hwwong168.wordpress.com/2015/11/19/building-grafana-for-raspberry-pi-2/" target="_blank">this guide</a>, but with a few changes to work with the Raspberry Pi B. You can download the resulting binary here (which is built from <span style="color: #555555; font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 11px; text-align: center;">v4.0.0-pre1 (commit: v3.1.0+226-g3077f99-dirty)</span>) and <i>if anyone asks</i> I'll do a short writeup on how to do this yourself. <b>Please leave comment if you're interested!</b> It involves installing node binaries, <a href="http://www.the-tech-tutorial.com/install-ruby-on-rails-4-0-1-and-rvm-on-raspbian-raspberry-pi/" target="_blank">ruby</a> and go. Most of these won't install 'the easy way' because the Pi B/B+/Compute Module/Zero don't feature the instruction set their newer brethren do.<br />
<h3>
</h3>
<h3>
To install my build from the Grafana <a href="https://github.com/grafana/grafana" target="_blank">master</a> branch</h3>
<span style="font-family: "courier new" , "courier" , monospace;">wget https://dl.dropboxusercontent.com/u/3261971/grafana-pi-armv5/grafana-4.0.0-pre1.g3077f99.deb?dl=1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">sudo apt-get update && sudo apt-get install linfontconfig1:armhf fontconfig-config -y</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">sudo dpkg -i grafana-4.0.0-pre1.g3077f99.deb</span><br />
<br />
After running the above, you should be able to get started using Grafana on your Raspberry Pi Compute Module, Model A/B/B+ and Zero!<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc-TCfZOtXl7Vs5zaThTETbQLmHe3OmAA89ZF0mNT-wMIXQoTi7K44RrHjeuIhNJbKTGIzN0Zdwj5cnjZMGc2Rue-DCPgyydqZcyxhuIZ-StD2d1jPWYT6ANy4uwIHPYDiMqN8Jy-34MYo/s1600/Screen+Shot+2016-08-21+at+11.00.13.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc-TCfZOtXl7Vs5zaThTETbQLmHe3OmAA89ZF0mNT-wMIXQoTi7K44RrHjeuIhNJbKTGIzN0Zdwj5cnjZMGc2Rue-DCPgyydqZcyxhuIZ-StD2d1jPWYT6ANy4uwIHPYDiMqN8Jy-34MYo/s200/Screen+Shot+2016-08-21+at+11.00.13.png" width="138" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Power consumption graph<br />
in Domoticz</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj85L8ZpTPdv0WbX-4TVi4uVtKXVZeakHKK2mlBAovMXql2jMbJnnKWUqko85NGe-Y5LlIFr3PRmYbJxZh4qsyf4Shulxgz3JnT-phKADTV58puSW0RDLNT3THbCOXi30yGXQJKccUPKClY/s1600/Screen+Shot+2016-08-21+at+12.09.12.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj85L8ZpTPdv0WbX-4TVi4uVtKXVZeakHKK2mlBAovMXql2jMbJnnKWUqko85NGe-Y5LlIFr3PRmYbJxZh4qsyf4Shulxgz3JnT-phKADTV58puSW0RDLNT3THbCOXi30yGXQJKccUPKClY/s400/Screen+Shot+2016-08-21+at+12.09.12.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Power consumption graph and indoor/outdoor temperature graph in Grafana<br />
You can see that the power consumption has more fluctuations at night time<br />
than the graphs from Domticz.</td></tr>
</tbody></table>
<br />Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com2tag:blogger.com,1999:blog-3004394666862334139.post-27883703169100724072016-08-14T13:42:00.000+02:002016-08-14T13:43:24.134+02:0011 Months Later: About productivity and mental health as a software devRecently I was asked whether I could share the tips and tricks that I still implement from my <a href="http://blog.thisiswhytheinternetexists.com/2015/09/about-productivity-and-mental-health-as.html" target="_blank">post from about 11 months ago</a>. At first, I wasn't even sure that I would be able to name things I've learned and managed to keep doing.<br />
<br />
Then I started thinking: is it even important that I can name them? Do I have to be consciously aware of the improvements I've made? But maybe the more important thing to realise is: even if I gain a single improvement from reading a book, something tiny that I did not do before, <b>it is a gain and it is worth it</b>! On top of that, everyones situation <i>is </i>different<i>. </i>This is why the stuff that helped me might not necessarily work for you.<br />
<br />
So in my opinion books like these should be used more like frameworks, toolboxes, but not as a manual or bible. Similar to how <a href="https://guntherverheyen.com/2013/03/21/scrum-framework-not-methodology/" target="_blank">this post</a> describes the concept of Scrum implementation:<br />
<blockquote class="tr_bq">
<span style="background-color: #f8f8f9; color: #666a76; font-family: "open sans" , "helvetica neue" , "helvetica" , "arial" , "lucida grande" , sans-serif; font-size: 16px;">The Scrum framework leaves different options and tactics to </span><a href="https://ullizee.wordpress.com/2013/01/17/ways-to-play-scrum/" style="border: 0px; color: #53a1b8; font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size: 16px; margin: 0px; orphans: 3; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline; widows: 3;" target="_blank">play the game</a><span style="background-color: #f8f8f9; color: #666a76; font-family: "open sans" , "helvetica neue" , "helvetica" , "arial" , "lucida grande" , sans-serif; font-size: 16px;">, ways that are at any time adopted to the context and circumstances.</span></blockquote>
Even if you implement only a small subset of the possibilities that Scrum provides, you're still benefiting from it and you can choose to combine it with other tools within (or even outside) the Scrum framework to streamline (optimise, improve, whatever) your work(flow) even more. This is something that is explained based on examples and anecdotes in the book <a href="https://www.infoq.com/minibooks/scrum-xp-from-the-trenches-2" target="_blank">Scrum & XP from the trenches, which you can download for free</a>!<br />
<h4>
In conclusion</h4>
While I don't want to sum up the things I do better because they might not work for you, I'll list the things I currently do and things that I wish I would be better at implementing. These are from <i>Blueprint of a productive programmer</i> as the other book (Becoming a better programmer) is basically a huge list of great advice that you should probably read every 4 weeks until you really think you're implementing > 10% of it :).<br />
<br />
Things I have learned and am able to implement (at least partially):<br />
<br />
<ul>
<li>Chapter 2 from Blueprint of a productive programmer: </li>
<ul>
<li>Minimise Distractions, Stay off Facebook (I actually uninstalled FB and WhatsApp from my phone)</li>
<li>Avoid meetings (unless it's REALLY clear what needs to be discussed for both parties and other means of communication will NOT suffice)</li>
<li>Commit to repository often (especially if you have trouble focussing because of stuff like A.D.D.)</li>
</ul>
</ul>
<div>
Stuff that I really want to do better (but have forgotten to actually keep doing)</div>
<ul>
<li>Chapter 5 from Blueprint of a productive programmer:</li>
<ul>
<li>Eat the right food</li>
<li>Take regular breaks</li>
<li>Prevent or treat RSI</li>
</ul>
</ul>
<div>
At the same time I found the book as a whole to give me a great insight in overall pitfalls in your daily routines as a programmer. If you're a programmer (and even if you're a pretty good programmer) I'm sure you will gain something from reading it :). Again, here are the books:</div>
<div>
<br /></div>
<div>
<h4 style="color: #2b0082; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 18px; line-height: normal; margin: 0px; position: relative;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Becoming a better programmer by <a href="https://www.blogger.com/profile/11084090457826022937" style="color: #5f28e1; text-decoration: none;">Pete Goodliffe</a>:</span></h4>
<span style="color: #333333; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; font-size: 13px;"><a href="http://shop.oreilly.com/product/0636920033929.do" style="color: #5f28e1; text-decoration: none;">O'Reilly Store</a>, <a href="http://www.amazon.com/Becoming-Better-Programmer-Handbook-People/dp/1491905530" style="color: #5f28e1; text-decoration: none;">Amazon</a> (<a href="http://www.amazon.com/Becoming-Better-Programmer-Handbook-People-ebook/dp/B00O5HOOU6/ref=mt_kindle?_encoding=UTF8&me=" style="color: #5f28e1; text-decoration: none;">Kindle</a>)</span></div>
<div>
<span style="color: #333333; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; font-size: 13px;"><br /></span></div>
<div>
<h4 style="color: #2b0082; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 18px; line-height: normal; margin: 0px; position: relative;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The Blueprint for a Productive Programmer by <a href="http://blog.mynameismosh.com/" style="color: #5f28e1; text-decoration: none;">Moshfegh Hamedani</a>:</span></h4>
<span style="color: #333333; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; font-size: 13px;">Amazon <a href="http://www.amazon.com/The-Blueprint-Productive-Programmer-Repetitive-ebook/dp/B00NALI4GS" style="color: #5f28e1; text-decoration: none;">ebook</a></span></div>
Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com3tag:blogger.com,1999:blog-3004394666862334139.post-90561392467955159302016-08-08T09:07:00.000+02:002016-08-08T09:07:02.369+02:00Tidying up the "server room"I have a NAS, a UPS, a Powerline adapter, a Philips Hue Bridge, an OpenTherm Gateway, and an OpenPi (Raspberry Pi Compute Module breakout board) in the hallway closet. There also was a 2nd gen Airport Extreme, but it has been replaced with a less power-hungry and more performant alternative. But even then, it was an utter mess.<br />
<br />
Unfortunately I have forgotten to make a 'before' picture, but I assure you, the empty space next to the NAS was filled with the items listed above. Wires everywhere. And even removing the Airport did not solve this.<br />
<br />
Then I decided, everything with mounting holes has to hang on the wall. And sometimes it's these small things that make a big difference. Mounting a piece of wood to the wall and putting some screws in allowed me to reduce the cable clutter (most of the cables can now be tucked away behind the NAS) and because the devices aren't laying all across the place, power cables are now routed together in a bundle.<br />
<br />
Now the only thing I have to do is wall mount the OpenPi. But I'll do that some other day. Even small improvements like this can make a great difference: it's so much easier to service a device without accidentally unplugging something else! Do yourself a favour and go after the low hanging fruit. You'll thank yourself later :)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw2T2ZdF-F1IBZnPLLiwki0t3a9yfMzgoBYjXLNOhja84hRHEr5ZJd6d9pdUUhbbAKrmK5QwDc6wb1nzUjOiygxOGxR1O9yKNN2x83mPQQb2sLe2r0D5pO17xB29Gfyo7vl2Lwhjukv2mt/s1600/DSC_0182.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="A picture of my "server room", the top part of our hallway closet. " border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw2T2ZdF-F1IBZnPLLiwki0t3a9yfMzgoBYjXLNOhja84hRHEr5ZJd6d9pdUUhbbAKrmK5QwDc6wb1nzUjOiygxOGxR1O9yKNN2x83mPQQb2sLe2r0D5pO17xB29Gfyo7vl2Lwhjukv2mt/s640/DSC_0182.JPG" title="" width="640" /></a></div>
Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-17183196817423310752016-05-21T17:28:00.002+02:002022-08-01T16:40:02.272+02:00So PalmOS is really dead now?<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIVRj73_hvTfqx8zB52gBwlIhcbn4zjaumDKvmomplcLDpkqmK2i485yKSUdu0ViyVgjsYvWvwrsHaJlrmt8YtxRJBatUYL7cCPdUWKbbJU_c8stpkbbqOKEHNhWa-ktG1_2cWhpk51kqh/s1600/t5_1.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIVRj73_hvTfqx8zB52gBwlIhcbn4zjaumDKvmomplcLDpkqmK2i485yKSUdu0ViyVgjsYvWvwrsHaJlrmt8YtxRJBatUYL7cCPdUWKbbJU_c8stpkbbqOKEHNhWa-ktG1_2cWhpk51kqh/s320/t5_1.jpg" width="320" /></a>I've been enjoying me PalmOS devices for quite some time now. First as an organizer and multimedia device and later as part of my collection of obsolete technology. What I really liked about PalmOS was it's speed and 'simplicity' if I may call it that. Of course I'm looking at an of from the past, knowing that there are a lot of OSes for portable devices that have a lot of features that PalmOS never had.<br />
<br />
In the past years I've had a Sony Clie <a href="https://en.wikipedia.org/wiki/Sony_CLI%C3%89_PEG-N760C" target="_blank">PEG-N760C</a> and a <a href="https://en.wikipedia.org/wiki/Sony_CLI%C3%89_PEG-NR70V" target="_blank">PEG-NR70V</a>. Later I upgraded to the <a href="https://en.wikipedia.org/wiki/Palm_Tungsten#Tungsten_T2" target="_blank">Tungsten T2</a>, then the <a href="https://en.wikipedia.org/wiki/Palm_Tungsten#Tungsten_T3" target="_blank">T3</a> and finally the LifeDrive (which I've <a href="http://www.palmpowerups.com/readarticle.php?article_id=10" target="_blank">upgraded to an 8GB CompactFlash card</a>). Of all those devices, only the T3 and the LifeDrive are still with me (and in working order :D). Recently I acquired a Palm Tungsten T|X, which was one of the last devices that Palm made before switching over to WebOS on the Pre series of smartphones. I was surprised to find that this device actually has received a patch/update to support WPA2 and WPA Enterprise! That is friggin AWESOME! While the Tungsten T|X only has Wireless B built in (802.11b = 11mbps) it works, and the device probably wouldn't be able to handle much more throughput anyway. Because the digitiser was broken, I ordered a new one from eBay, and it was pretty easy to replace it. It seemed like I had a high-end PalmOS device with WiFi, Bluetooth and a "high res" screen.<br />
<br />
This is how I got started on wanting to revive PalmOS, at least from a developers perspective. I wanted to write (or port) a <a href="http://jansson.readthedocs.org/" target="_blank">JSON library</a> and use it to interact with REST API's or something. Or a remote control for my home automation system. Or basically anything that I could code that did not exist yet for PalmOS. But I hit a few roadblocks.<br />
<br />
<h4>
Lack of documentation and community</h4>
There isn't a lot of 'publicly available' documentation on PalmOS development. While the SDK docs can be found in some of the deep dark corners of the web, and a development environment can be set up, there is just no active community at all. It seems like development has stopped for about 10 years (or more!) and all what is left is these obsolete devices that are not able to use most of their functionality. Considering the fact that the devices aren't sold anymore, there is no market for software development on PalmOS and you're not actually gaining anything other than personal satisfaction (most people have forgotten that PalmOS existed at all!) this seems reasonable.<br />
<br />
<h4>
SSL Certificate support is limited to SHA1</h4>
While some tools exist to convert CA root certificates to PDB files, the PalmOS does not support SHA256 certificates. This means that most of the HTTPS interwebs is not reachable from the browsers, and secure communication is basically impossible. Most companies that have a WPA2 Enterprise-secured WiFi-network use an SHA256 certificate and this makes using the Tungsten T|X on a corporate network (or country-wide WiFi-hotspot network like the Dutch <i>Ziggo WiFiSpots</i>) impossible. SHA256 has been used in at least one application that I know of, pssh2. Unfortunately re-using this code in an application and rewriting part of PalmOS are two different things.<br />
<br />
<h4>
So what can we still do with our legacy devices?</h4>
When these devices were still awesome, a lot of cool stuff has been made. And because the internet was not as big as it is today, most of these apps work offline! Over the next few weeks I'm going to show a few applications that I've used in the past decade and might be nice for you to re-live the PalmOS days again :).<div><br /></div><h3 style="text-align: left;">Felix from the 2022 here:</h3><div>The PalmDB community strives to host files for abandoned projects as well as ROMs for devices and other useful tools. Check it out <a href="https://palmdb.net/" rel="nofollow" target="_blank">here</a>. They have a <a href="https://discord.gg/YddKPpR" rel="nofollow" target="_blank">Discord</a> as well! Also <a href="https://dmitry.gr/" rel="nofollow" target="_blank">Dmitry Grinberg</a> is<a href="https://dmitry.gr/?r=05.Projects&proj=27.%20rePalm" rel="nofollow" target="_blank"> hacking Palm OS like there is no tomorrow</a>, and there is a guide on how you can get started with a toolchain for PalmOS development <a href="https://palm2000.com/projects/compilingAndBuildingPalmOsAppsOnUbuntu2004LTS.php" rel="nofollow" target="_blank">here</a>. Of course there is a subreddit as well: <a href="https://www.reddit.com/r/Palm/" rel="nofollow" target="_blank">/r/Palm</a>. Have fun!</div><div><br /></div>Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com2tag:blogger.com,1999:blog-3004394666862334139.post-61980048757773716292016-05-01T13:54:00.000+02:002016-05-01T13:54:17.756+02:00Unbricking the HM-10 BLE module on the OpenPiI've been doing some home automation testing using the <a href="https://www.kickstarter.com/projects/wirelessthings/openpi-wireless-computer-for-inventors-makers-and/description" target="_blank">OpenPi</a> because of it's small footprint, internal RTC and the cute case that was created for it. As a cherry on top, they also included an SRF/XRF module and a Bluetooth LE (HM-10) module so you can remotely open a shell using a Bluetooth-enabled device and an app.<br />
<br />
My goal was to scan for devices in the neighborhood and determine whether me or my girlfriend is home so we can turn down the central heating. Using the information found in a <a href="https://www.seeedstudio.com/wiki/images/c/cd/Bluetooth4_en.pdf" target="_blank">document explaining the available AT commands</a> I got no response to the scanning command. I decided to update the firmware of the HC-10. I can now safely say that I have confirmed the module in the OpenPI to be the TI CC2541. In the flashing manual the following message can be found:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc7wUcZiJQxnl3mnND9-Vjkc_eYRHDZ7Lk2lYO7p1tqmdWWv2zMQI-TcKM1dn5fMfcCqxhuZVBkUKv2WrotoLEAF9dCgFbl40PtdSbMI6x1uCcacM01LgkCwZRcsGEdb3vzbo-B_NMbQbq/s1600/Screen+Shot+2016-05-01+at+12.57.50.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Note: this operation is not reversible, please be sure to note, after the operation is completed, if you don't want to upgrade, the module will not return not normal working mode." border="0" height="66" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc7wUcZiJQxnl3mnND9-Vjkc_eYRHDZ7Lk2lYO7p1tqmdWWv2zMQI-TcKM1dn5fMfcCqxhuZVBkUKv2WrotoLEAF9dCgFbl40PtdSbMI6x1uCcacM01LgkCwZRcsGEdb3vzbo-B_NMbQbq/s320/Screen+Shot+2016-05-01+at+12.57.50.png" title="" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
I assumed that no firmware manufacturer could ever actually write firmware that could leave the device in a bricked state unless you provide firmware. What if the device isn't actually connected to a windows pc? Well, after issuing the software upgrade command that was exactly the situation I was in.<br />
<br />
To save you the trouble, the tool that Huamao Technology provides does not work correctly using the workaround I did to flash the HM-10 on my OpenPi. Luckily the <a href="http://processors.wiki.ti.com/index.php/File:SerialBootTool_1_3_2.zip" target="_blank">tool provided by the manufacturer of the bluetooth chip</a> DOES work! So download the firmware from <a href="http://www.jnhuamao.cn/download_rom_en.asp?id=" target="_blank">Huamao's site</a> (HM-10, CC2541) and follow the next few steps to bring your HM-10 back from the dead.<br />
<h4>
<b><br /></b><b>Requirements</b>:</h4>
<br />
<ul>
<li>A Windows (virtual) machine to run the update tool on</li>
<li>Raspbian or similar image on your OpenPi, SSH enabled</li>
<li>A network connection between your Windows PC and OpenPi</li>
<li>socat and minicom installed on your OpenPi (<span style="font-family: Courier New, Courier, monospace;">sudo apt-get install socat minicom -y</span>)</li>
</ul>
<br />
<br />
<h4>
<b>Step 0:</b> (<b>if you did not brick the HM-10 yet</b> but are feeling adventurous) set the HM-10 module to Software Upgrade mode:</h4>
ssh into your raspberry pi.<br />
<br />
Run: <span style="font-family: 'Courier New', Courier, monospace;">minicom -s</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
A menu opens. You want to select "Serial Port Setup", Press 'A', replace ttyUSB0 with ttyS0 (assuming this is the device that your HM-10 is connected to), press Enter.<br />
<br />
Setting E should be set to 9600 8N1. If this is not the case, press E, then C, then Enter.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2ENkcbUGC2ao7ZQILzc4W_MF3BLMFtDUHUvhgOHA2g85mQ_7q9BAb79JaeMe9v_oxqO7R3uib5UL8jlSjiW-m88wPnFouhSTtqh9d14VvM6EcEICbYxalQcMSZhYQhDlSrfnT3C7NATYt/s1600/Screen+Shot+2016-05-01+at+13.09.45.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2ENkcbUGC2ao7ZQILzc4W_MF3BLMFtDUHUvhgOHA2g85mQ_7q9BAb79JaeMe9v_oxqO7R3uib5UL8jlSjiW-m88wPnFouhSTtqh9d14VvM6EcEICbYxalQcMSZhYQhDlSrfnT3C7NATYt/s320/Screen+Shot+2016-05-01+at+13.09.45.png" width="320" /></a></div>
If your screen looks somewhat like the screenshot above, press Enter. You should now see the minicom menu. Select Exit to open the session. You will not see what you're typing. If you prefer seeing what you type, press Ctrl + A, then Z, then E. This turns on the "Echo".<br />
<br />
Then paste the following command to place the module into Software Upgrade mode:<br />
<br />
<br />
<div class="page" title="Page 2">
<div class="layoutArea">
<div class="column">
<span style="font-size: 11pt;"><span style="font-family: Courier New, Courier, monospace;">AT+SBLUP</span></span><span style="font-family: 'MicrosoftYaHei'; font-size: 11.000000pt;"> </span><br />
</div>
</div>
</div>
<br />
After this your device will be in Upgrade mode. You can exit minicom by pressing Ctrl + A, Q and answering 'Yes'.<br />
<br />
From this point on, the HC-10 module switches to 115200 baud for the software upgrade.<br />
<h4>
<b><br /></b></h4>
<h4>
<b>Step 1</b>: Start Socat on the Raspberry Pi</h4>
To provide raw TCP access to the bluetooth modules serial interface, run the following command:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">while true; do</span><br />
<span style="font-family: Courier New, Courier, monospace;"> socat tcp-listen:54321,reuseaddr /dev/ttyS0,b115200,raw,echo=0</span><br />
<span style="font-family: Courier New, Courier, monospace;">done</span><br />
<br />
This command makes socat listen on port 54321, and if the server is stopped by a reset command, a new server is started.<br />
<h4>
<b><br /></b></h4>
<h4>
<b>Step 2</b>: <a href="http://www.eltima.com/products/serial-over-ethernet/" target="_blank">Install Eltima Serial to Ethernet connector</a> (trial) on your Windows machine</h4>
Download the trial, install it and open the program that is installed on your machine.<br />
<br />
<h4>
<b><br /></b></h4>
<h4>
<b>Step 3</b>: Create a connection to your socat instance on the pi:</h4>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwWvEk0GHfiy0yTOkBgbyif1IyrNBtny-2Pf7I_IRHBwvwicBGh0fNxiDJpe_8Wtbm1R96IFR4TtNO0BCmGbp0AcXDX7gOLwNYpEDbMhGHIJLb5vPRDVgckYwcxTkvqZasv6E1O8sch7DY/s1600/Screen+Shot+2016-05-01+at+13.23.58.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwWvEk0GHfiy0yTOkBgbyif1IyrNBtny-2Pf7I_IRHBwvwicBGh0fNxiDJpe_8Wtbm1R96IFR4TtNO0BCmGbp0AcXDX7gOLwNYpEDbMhGHIJLb5vPRDVgckYwcxTkvqZasv6E1O8sch7DY/s200/Screen+Shot+2016-05-01+at+13.23.58.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This is what the setting should look like.<br />Replace the hostname with the IP of<br />your OpenPI.</td></tr>
</tbody></table>
- Choose 'create a client connection'<br />
- Select an unused COM-port number (I chose COM3)<br />
- Fill in the remote hostname (IP address of your OpenPI)<br />
- Fill in the port number (54321, the socat listening port)<br />
- Open 'Advanced Settings'<br />
- Disable 'Connect to Remote end only when local virtual port is open' checkbox<br />
- Enable 'On error retry to establish connection every' checkbox, and set its value to 100ms.<br />
- Press 'Apply Changes'<br />
<br />
<h4>
<b><br /></b></h4>
<h4>
<b>Step 4</b>: Install and open the TI SerialBootTool.</h4>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpb8x4z7rmpJbhK7SUmZfklHYxkIjRWZOG_AFuyTHSLhyphenhyphenhi938cNTb6QGnVtncGJzqf1z_rHhl1Lxz8Xntm8wdHaJ41dSg6-pWKupl751KQ6n_TKOfuqHxo8yES8m5U3POKZKoZW9IL0kF/s1600/Screen+Shot+2016-05-01+at+13.49.39.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="168" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpb8x4z7rmpJbhK7SUmZfklHYxkIjRWZOG_AFuyTHSLhyphenhyphenhi938cNTb6QGnVtncGJzqf1z_rHhl1Lxz8Xntm8wdHaJ41dSg6-pWKupl751KQ6n_TKOfuqHxo8yES8m5U3POKZKoZW9IL0kF/s320/Screen+Shot+2016-05-01+at+13.49.39.png" width="320" /></a></div>
<br />
<h4>
<b><br /></b></h4>
<h4>
<b>Step 5</b>: Select the firmware file and serial port. </h4>
After selecting the serial port, press the 'Open' button.<br />
<br />
<br />
<h4>
<b>Step 6</b>: Flash away! </h4>
After flashing and verification (which may take a while, approx. 5 minutes?) you should be good to go!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM2pO83o6rDswCJIIMuCUlUU3jLT5J4lGCxpmCyNov33mp84pwrenrDal3zYmqTd86qA1slDpvAvJIptHGNuAjRUVD7IInSqBrlPZaOeyQFJ-BtVVPqm1ZOovi50oxRYijICADC6MGSNae/s1600/Screen+Shot+2016-05-01+at+13.46.19.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="168" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM2pO83o6rDswCJIIMuCUlUU3jLT5J4lGCxpmCyNov33mp84pwrenrDal3zYmqTd86qA1slDpvAvJIptHGNuAjRUVD7IInSqBrlPZaOeyQFJ-BtVVPqm1ZOovi50oxRYijICADC6MGSNae/s320/Screen+Shot+2016-05-01+at+13.46.19.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This should be the result of your hard work!</td></tr>
</tbody></table>
Of course, because of the while loop, we started on the Pi it is probably best to close the session where the loop is run. This will also kill the loop. Otherwise, just restart the pi by unplugging the MicroUSB plug providing power to the device.<br />
<br />
<h4>
<b>Other helpful and somewhat related HM-10 resources:</b></h4>
http://smoothieware.org/bluetooth-serial<br />
https://github.com/WirelessThings/OpenPi/blob/master/gettingstarted.rst<br />
http://openmicros.org/index.php/component/kunena/14-openpi/11317-bluetooth-module?Itemid=0<br />
https://github.com/RedBearLab/CCLoader/blob/master/Arduino/CCLoader/CCLoader.ino<br />
http://raspberrypi.stackexchange.com/questions/15382/raspberry-pi-used-as-a-cheap-serial-to-wlan-converter<br />
<br />
<br />Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-12546899006610879082016-04-27T17:37:00.000+02:002016-04-27T17:37:14.210+02:00So why don't Google and Azure have full IPv6 connectivity yet?For my company I've been using different cloud providers in the past years. One of the things I noticed is that Google, Amazon and Azure currently don't offer IPv6 connectivity for virtual machines at all! The following is Google's <a href="https://cloud.google.com/compute/docs/networks-and-firewalls" target="_blank">statement</a> at the time of writing:<br />
<br />
<blockquote class="tr_bq">
<span style="background-color: white; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 22.4px;">All Compute Engine networks use the </span><a href="http://tools.ietf.org/html/rfc791" style="background-color: white; color: #4285f4; font-family: Roboto, sans-serif; font-size: 14px; line-height: 22.4px; text-decoration: none;">IPv4</a> <span style="background-color: white; color: #222222; font-family: Roboto, sans-serif; font-size: 14px; line-height: 22.4px;">protocol. Compute Engine currently does not support IPv6. However, Google is a major advocate of IPv6 and it is an important future direction.</span></blockquote>
Azure <a href="https://azure.microsoft.com/en-us/pricing/faq/" target="_blank">states</a> something similar:<br />
<blockquote class="tr_bq">
<span style="background-color: white; color: #505050; font-family: 'Segoe UI', 'Segoe WP', Tahoma, Arial, sans-serif; font-size: 16px; line-height: 24px;">Microsoft has played a leading role in helping customers to smoothly transition from IPv4 to IPv6 for the past several years. [...] The foundational work to enable IPv6 in the Azure environment is well underway. However, we are unable to share a date when IPv6 support will be generally available at this time.</span></blockquote>
So how is this even possible? I understand that there are technical challenges, but IPv6 has been around for years and these guys really are really big players in the cloud market!<br />
<br />
So what ARE your options for native IPv6?<br />
Well, basically you can use an <a href="http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-internet-facing-load-balancers.html" target="_blank">Amazon load balancer</a> with IPv6 support, create a tunnel for IPv6, or use another hacky solution, but for now I'm afraid native (and vendor supported) IPv6 is only available with smaller hosting companies, <a href="http://www.softlayer.com/" target="_blank">Softlayer</a> and <a href="https://www.linode.com/" target="_blank">Linode</a> being great examples of providers that do offer IPv6 with virtual machines. But if you require specific vendor services from Google, Amazon or Microsoft you'll be left without official IPv6 support for VM's. At least, for now.Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-6724964622122715652016-03-13T21:14:00.002+01:002022-05-01T13:23:34.069+02:00Introducing the Epoch WebService for Low-Power IoT devices without RTC<div><b>Edit: the epoch service is down. There are so many alternative ways to do something like this. </b></div><div><br /></div>Today I was working on the <a href="https://github.com/DJFliX/OakPowerBoard" target="_blank">OakPowerBoard</a> project and I asked myself: why isn't there a web service that just allows you to get the current Unix Timestamp without having to parse loads of response data? Well, I couldn't find it! So I built it and deployed it to Azure! Until I find a shorter domain you can use the following URL as you see fit!<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> <a href="http://tiwtieapp.azurewebsites.net/now?format=json">http://tiwtieapp.azurewebsites.net/now?format=json</a></span><br />
<br />
This will return the server time. No padding, no trimming, just the time! Neat, right? I've contacted the owner of epo.ch, but haven't had a response yet.<br />
<br />
<b>So why did I do this?</b><br />
The OakPowerBoard firmware does HTTP requests anyway, so doing a request to this web service does not cost a lot of extra code. Implementing a bare-bones NTP client is probably a lot more work! And of course, nearly every internet-connected platform has examples for a simple HTTP GET request, this cannot be said for NTP. Enjoy!Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-59977078607846819962016-02-21T16:59:00.000+01:002016-02-21T17:18:14.024+01:00Oak Power Board, Part 1I've been meaning to do a small write-up on my latest project, and add-on board for <a href="https://www.kickstarter.com/projects/digistump/oak-by-digistump-wi-fi-for-all-things-arduino-comp/" target="_blank">DigiStump's Oak</a> board; an <a href="https://en.wikipedia.org/wiki/ESP8266" target="_blank">ESP8266</a>-<a href="https://www.kickstarter.com/projects/digistump/oak-by-digistump-wi-fi-for-all-things-arduino-comp/description#project_faq_131455" target="_blank">ish-based</a> mini board with an on-board LDO that is programmable with the Arduino IDE using <a href="https://www.particle.io/" target="_blank">Particle Cloud</a>. The Oak was successfully funded using KickStarter and I got my board pretty fast! While the firmware is <a href="https://www.kickstarter.com/projects/digistump/oak-by-digistump-wi-fi-for-all-things-arduino-comp/posts/1497200" target="_blank">not yet finished</a> I've been able to make a prototype and think about what I wanted to do with a cute Arduino-IDE-compatible-wifi-equipped-board like this. You can find the project on <a href="https://github.com/DJFliX/OakPowerBoard" target="_blank">GitHub</a>.<br />
<br />
<h3>
Creating a Power-consumption monitoring device</h3>
<div>
I've recently moved in with my girlfriend (who does <a href="http://www.hannighan.com/" target="_blank">awesome drawings</a>, by the way!) and because this meant having to pay the electricity bills ourselves I wanted to know whether we would have to pay extra (for consuming more electricity and gas than anticipated) or that we'll receive money for consuming less of both. I was also interested in how much energy was consumed at a given time of day. This helps us decide which devices to keep plugged in in stand-by, and which devices to fully unplug. Because I'd heard of some Arduino-based projects using an TCRT5000 to do just this, I decided I wanted to design a board to do the same, but instead it would be cheaper, easier (both to use and to update, thanks to Particle OTA updates), and smaller than a regular Arduino.</div>
<div>
<br /></div>
<h3>
<a href="https://cdn.rawgit.com/DJFliX/OakPowerBoard/master/images/DSC_1045.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="188" src="https://cdn.rawgit.com/DJFliX/OakPowerBoard/master/images/DSC_1045.JPG" width="200" /></a></h3>
<h3>
Prototype</h3>
<div>
After some prototyping I decided on using an SSD1306 OLED display (128x64 pixels) that I has lying around at work. I hooked it up, and (fortunately!) someone had already written a <a href="https://github.com/squix78/esp8266-oled-ssd1306" target="_blank">library</a> to use the SSD1306 on the ESP8266. As Particle handles WiFi connectivity that meant that the only thing I had to do was write code to calculate the time between pulses of the <a href="http://www.britannica.com/technology/watt-hour-meter" target="_blank">KWh-meter</a>, and I should be good to go, right? So I decided to design a PCB to put the Oak, the TCRT5000 and the SSD1306 display on.<br />
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<h3>
<a href="http://digispark.s3.amazonaws.com/OakByDigistump.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://digispark.s3.amazonaws.com/OakByDigistump.png" height="197" width="320" /></a>Designing the first board (also: the first mistake)</h3>
<div>
Because the prototype seemed to do what it should, I put a PCB design together and sent it to OSH-park. I received the boards pretty soon, and I was happy with them, until I tried to get measurements from the TCRT5000. I had forgotten to check whether we would be using the TCRT5000 input as analog or digital. Where the Arduino has a lot of ports to use (usually 6 or more analog, and a lot more of the digital kind), <b>the Oak has only a single port that is able to do analogRead</b> (port 0). Fortunately I had been using port 5, so I could add a bodge-wire and continue with my firmware.</div>
<div>
</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="clear: right; float: left; margin-bottom: 1em; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifyaOTWbK1E18fd8T0iAXptYKcqNijzyILQ_uHAe8GLbcXldv2g4mUb-JH-r6_MwTHikCODXPYGABdiyR2PXrC3942nMo27xRd4zQ9DjVgcUcwOHhb8DcpHJHZgrmgVzz8iq326RYjOpZ5/s1600/DSC_1062.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifyaOTWbK1E18fd8T0iAXptYKcqNijzyILQ_uHAe8GLbcXldv2g4mUb-JH-r6_MwTHikCODXPYGABdiyR2PXrC3942nMo27xRd4zQ9DjVgcUcwOHhb8DcpHJHZgrmgVzz8iq326RYjOpZ5/s320/DSC_1062.JPG" width="320" /></a> </td></tr>
<tr><td class="tr-caption" style="font-size: 13px; text-align: center;">The bodge-wire in question, redirecting the sense-pin connected <br />
to the TCRT5000 to the only analog pin on the Oak</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
On a side note: I really like the board as it is. OSH-park is great and I would recommend it to anyone who wants to do a small prototype run. Compared to services I've used, the web-based interface is easy and shows renders of how the board will look. Every layer is separately rendered and I've been able to spot some mistakes before sending the board to fab. The purple color is funky, and of course that also counts for something, right?</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br />
<br /></div>
<h3>
Current stage of the project</h3>
<div>
The latest developments on the board have been that I'm currently not able to reliably attach the board to my KWh-meter. This means I can't write/test code at the moment, but I hope to be able to test this soon. If pulse detection works I can do some tests on other meters and find a way to semi-permanently attach the device to anyones (spinning disk type) KWh meter.</div>
<div>
<br /></div>
<div>
If you want to check it out, go to <a href="https://github.com/DJFliX/OakPowerBoard" target="_blank">github</a>. Both the board and the code files are there. I've opened a topic on the digistump boards for this project, so if you already have an account there, you can also contact me in the <a href="http://digistump.com/board/index.php/topic,1975.0.html" target="_blank">topic</a> on the <a href="http://digistump.com/board/index.php/board,22.0.html" target="_blank">Projects</a> board. If you have any suggestions, contact me or leave a message. Thanks for reading! </div>
<h3>
</h3>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-23299941749631071202016-02-21T16:21:00.002+01:002016-02-21T16:21:31.943+01:00Update on recent developmentsHi All! As you might (or might not) know, I have my own company (thisiswhytheinternetexists), but I also work at QwikSense, which is my other company that I co-founded. As QwikSense has some spare server capacity I'm able to use that for TIWTIE as hosting that doesn't need a lot of resources anyway. Unfortunately that is the reason that my site has been down for the past few days: QwikSense moved from Google Cloud to Microsoft Azure, and I didn't have the spare time to fix the site. Luckily, I found some time to do this today, and as you might be able to see, it's up and running again! Yay!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_JIoSSrHR2NNooKy2JsOKHhOHlG_cyi2vjCLk7YJgrhULF4S-LhGAZV9kKpbkvKmCvncsdd9-7HklDk0xgZW90KVdG-Pc3wzc8a1AsO8RwYtJlmfwgJH3qmDIf_lUQItQT9PVOTcaP7pq/s1600/Screen+Shot+2016-02-21+at+16.21.14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_JIoSSrHR2NNooKy2JsOKHhOHlG_cyi2vjCLk7YJgrhULF4S-LhGAZV9kKpbkvKmCvncsdd9-7HklDk0xgZW90KVdG-Pc3wzc8a1AsO8RwYtJlmfwgJH3qmDIf_lUQItQT9PVOTcaP7pq/s400/Screen+Shot+2016-02-21+at+16.21.14.png" width="400" /></a></div>
Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com0tag:blogger.com,1999:blog-3004394666862334139.post-91243210627623128442015-09-07T21:30:00.000+02:002015-09-07T21:33:30.956+02:00About productivity and mental health as a software dev<h2>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Hello World!</span></h2>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">As an experiment I'll be posting stuff about my life, work, ideas and more. Depending on the responses I'll consider putting more effort in this. Expect nerd stuff, me bragging about the awesome hardware I purchased second hand and me raving about the next best thing to build your web service with.</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">I'm not usually someone who reads books often, but in the past few weeks I've made a change in the way I spend my day at work. The changes were minimal but allowed me to be a little more physically active and decrease the time I spend frustrated while trying to solve problems in our web service back-end. The changes I made were inspired by two books, </span><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><i>The Blueprint for a Productive Programmer: How to Write Great Code Fast and Prevent Repetitive Strain Injuries</i> by </span><a class="a-link-normal contributorNameID" data-asin="B00NATDQ5Y" href="http://blog.mynameismosh.com/" style="color: rgb(153, 102, 51) !important;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Moshfegh Hamedani</span></a><span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> and <i>Becoming a better programmer</i> by </span><a href="https://www.blogger.com/profile/11084090457826022937" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Pete Goodliffe</a><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">. Links to the books in different stores will be at the bottom of this post. I didn't finish <i>Becoming a better programmer</i> yet but I'm plan on finishing it soon. </span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">As I usually don't really read any book at all (my work research is mostly on-line) I found it a really nice way to read a lot of stuff that wasn't necessarily something I was Googling for. Both books are meant for programmers that are passionate and are focused on making yourself function more optimal in situations where you need to deliver code fast and pressure is usually high. Small tips and tricks help you optimise the way you handle your work day and how you plan it. I recommend both books to anyone who feels that your work could be easier but doesn't know what he/she is currently doing wrong to prevent this. </span><br />
<br />
<h3>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif; font-size: small;">The Blueprint for a Productive Programmer</span></h3>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">This book handles mostly concerns related to physical health (and the effects of long term physical strain on your ability to continue doing your job), managing your time more efficiently, minimise distractions, and improve your mental health. I feel that really any programmer should read this, the book is worth it's weight in gold! Very practical and easy to read. But as the author states in the book: </span><br />
<blockquote>
“Reading this book is one thing, putting it into action is another. If you don’t practice what you learn in this book and continue with your bad habits, you’ll be just wasting your time. ”</blockquote>
<span style="font-size: x-small;">Excerpt From: Moshfegh Hamedani. “The Blueprint for a Productive Programmer: How to Write Great Code Fast and Prevent Repetitive Strain Injuries.”</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">I guess the best thing is to do what I did, start reading and if you feel that you won't be able to implement change, just stop reading. I actually forgot about that until in finished the book :). </span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">I'll be writing about Becoming a better programmer in a next post. If you have any questions or comments, fire away!</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<br />
<h3>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Links to the books:</span></h3>
<h4>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">The Blueprint for a Productive Programmer by <a href="http://blog.mynameismosh.com/">Moshfegh Hamedani</a>:</span></h4>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Amazon <a href="http://www.amazon.com/The-Blueprint-Productive-Programmer-Repetitive-ebook/dp/B00NALI4GS">ebook</a></span><br />
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><br /></span>
<br />
<h4>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Becoming a better programmer by <a href="https://www.blogger.com/profile/11084090457826022937">Pete Goodliffe</a>:</span></h4>
<span style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><a href="http://shop.oreilly.com/product/0636920033929.do">O'Reilly Store</a>, <a href="http://www.amazon.com/Becoming-Better-Programmer-Handbook-People/dp/1491905530">Amazon</a> (<a href="http://www.amazon.com/Becoming-Better-Programmer-Handbook-People-ebook/dp/B00O5HOOU6/ref=mt_kindle?_encoding=UTF8&me=">Kindle</a>)</span>Felix Mannhttp://www.blogger.com/profile/08341513499400830056noreply@blogger.com2Utrecht, Netherlands52.090737399999988 5.12142010000002351.934617399999986 4.7986966000000226 52.246857399999989 5.4441436000000234