Tuesday, February 27, 2018

Retain format / style of text pasted into Gmail composition

While coding, there are cases one will want to keep important code snippets into a private repository using Gmail. That's what I wanted to do, and what I actually did. Or one may want to send it to their friends to help them.

I prefer keeping the original formatting of the IDE to losing them while pasting. Unfortunately, simple copy from the IDE and paste into Gmail sometimes worked but not always. Google search gave results mostly about how to remove annoying formatting instead of how to retain them, quite frustrating.

There is one option one to check:


If the 'plain text mode' is checked in the mail composition window (unchecked in the above image), then you will see the contents pasted there only. Formatting is all gone.

Saturday, February 24, 2018

Extending life expectancy of USB external hard drive

I have long used two desktops; one at home, one at work. For working storage, external HDD was my choice since I didn't like having my data saved on a commercial cloud service for which I have little control. (A definitely outdated and inefficient way; I now use cloud at least partially). So far I used three different external HDDs. 1TB from Seagate / Toshiba / Western Digital. The first two gradually died in about a year, but the last and the current one survived over 3 years and 4 months. In fact this baby showed some death sign recently, so I bought another one, but I didn't have to open the package.


The biggest difference is that I paid a lot of attention with the current one when disconnecting it from desktop. In the past I force unplugged USB cable even at the error message saying 'Windows can't stop your device upon ejection attempt, assuming it be okay since the read / write process should be completed. Now I have it a rule to set the HDD offline first upon ejection failure, although I still force unplugged infrequently. Probably less than 1%.

One needs to go to Control Panel -> Administrative Tools -> Computer Management -> Disk Management, right click and HDD, and then check 'offline'.


Note that, if you disconnect the HDD after setting it offline and reconnect, then the autoplay doesn't pop up, and the HDD won't be visible in the Windows Explorer. You have to manually set it back to online using the same context menu as the above. This could be a problem in particular when you come to work the next day, but do not remember that you manually have set the HDD offline. So I typically reconnect the HDD and restore to online right away.

I do not clearly remember the symptoms of dying HDD since I haven't had the issue for the last ~3 years, but I think being unable to eject your HDD normally progressively more often was one of them. By then, you might start seeing warning like 'this device can perform faster if you connect to USB 3.0 port blah blah..' even though it is connected to USB 3.0 port. Or FAT system of the HDD becomes corrupt so that you cannot read some files. In the end your entire HDD becomes inaccessible. Or you will see a message like 'this drive is not formatted. will you want to format?'.

In short, I strongly recommend you to safely disconnect your HDD; meaning that you should make sure that the HDD is truly ready to be disconnected, sometimes by manually setting if offline.

Tuesday, February 20, 2018

Imitating NYC subway control center using Google Map

I recently came to learn that, in an effort toward open data project, New York city MTA (Metropolitan Transportation Authority) offers API feeds for quasi-real-time subway traffic data. Then, wouldn't it be nice if I can plot the train locations on Google map, and make a movie of screen shots taken at an interval? It should look something like a grand monitor screen in a control center. So I started this brief self-project.

Understanding API feeds, and basic analysis of the returned data were done with Python, but the real code was written in PHP and Javascript. More specifically, back-end task such as feed query / parsing / translation of station ID into GPS latitude + longitude pair were implemented with PHP + MySQL, and front-end Google Map plot with Javascript-based Google Maps API. The entire codes are available in my GitHub repository. The outcome looks like below. You can execute yourself here. Note that the page does not update by itself; you need to manually refresh the page.

The data are not truly real-time since MTA DB is not updated every seconds or more often. (Technical reasons will be spelled out below for those who are interested). So I do NOT guarantee precision of the markers. At this point this is a just-for-fun project. I learned basic components of web development using Python / PHP / MySQL / Javascript / xml / API (MTA, Google Maps) / Node.js despite not very deep. Which made me to re-realize how much failed trial and attempts a success demands. Hope you enjoy.


[Technical issues]
1. Statistical analysis of MTA feed revealed that the data are approximately 99 seconds old (with 28 seconds of standard deviation). Quasi but not truly real time.

2. The feed returns only the last station a train stopped at the moment of query, not a location in between. That's why all trains seem to be at a station, which must not be true at all. Also that is why it is very likely for you to see multiple trains at one stop. You might need to zoom all the way in to distinguish them.

3. MTA tells user only the stop sequence number, which has to be properly translated to unique station ID. This is a complicated job since the total number of stops depend on a variety of factors such as: (1) daytime or late night? (2) weekday or weekend? (3) express? (4) any temporary service change due to construction? I could extend the application so that it can incorporate all of these variation, but not yet.

4. Raw data from MTA shows a few trains at the terminal station. They are not shown on the map just for convenience.

Monday, February 19, 2018

NYC subway expired Metrocard ticket trade-in

You find that your NYC subway Metrocard expired but it has some money in it. Can you trade in for another one with new expiration date? The answer is YES. No fee, fully on a vending machine. Here's my story.

I definitely have past experience with trading in an expired Metrocard to a new one. But back then I asked a staff sitting in a station vestibule. This time I had an Airtrain JFK Metrocard, and the lady in Woodside station in Queens said there is nothing she could do there. So I had to go to Jamaica station (fortunately I had to go there anyway to take an LIRR train). I asked an assistance standing next to a turnstile to JFK airtrain what to do. She said, surprisingly, it has expired, so there is nothing I could do. NO, that must not be true. I decided to try myself on the vending machine. And I did, as you see in the screen shot:

I forgot how I've got to that menu but I think I chose either Metrocard info or refill a Metrocard at the beginning and then inserted the expired card. Then the machine asked me to remove it, and it gave me a new one with exactly the same amount transferred plus receipt (probably because I chose to receive receipt). It was that easy and quick and convenient. You can do it too!



Here is the link to the MTA instruction. Which says:


Whether Pay-Per-Ride or Unlimited Ride, every MetroCard has an expiration date. The date is located at the upper left corner on the back of the card. The expiration date is usually about one year from the date of purchase. If your Pay-Per-Ride MetroCard expires, you have two years from the expiration date to transfer any remaining money to a new card. Within the first year after expiration, bring your expired card to any subway station and ask the agent to make the transfer. After that time, the expired MetroCard must be sent to MetroCard customer claims. Ask the station agent for a postage-paid Business Reply Envelope.

Thursday, February 15, 2018

Automatically building a UHV chamber 3D CAD model using VBA Solidworks API

Let's start with a Youtube movie. It captures the process of generating 3D CAD model of a UHV (ultra high vacuum) chamber at a mouse click using Solidworks API. VBA source code was executed on Visual Studio Community 2017, driving 2017 version of Solidworks. The entire process from 3D sketch skeleton to chamber main body to final assembly containing CF flanges properly mated in the correct positions and orientations is fully automated. Intermediate files are all cleared, leaving the final assembly only on the screen at the end. A highly efficient method particularly during chamber designing stage, since one only needs to change a few numbers defining port geometry and simply re-run the code if ports need to be moved / added / deleted / etc. In other perspective, mouse click and keyboard input by user in conventional Solidworks GUI are all converted to corresponding code, so that the whole script can be sequentially batch-executed all at once.

Solidworks API official documentation is not of high quality, probably because it serves small community of API programmers. Even worse, I had little experience not only with the API but also the Visual Basic itself. So there were so countless times in which the code snippet generated by Solidworks Macro didn't work when imported to VBA, and in which I could not find help from extensive Google search. In fact I chose VBA out of different languages since most of the helpful comments available online was for VBA. But I still had to waste hours occasionally trying to figure out what to do to make it work the way I wanted. This article is to summarize and share my knowledge and know-how obtained therefrom with wider public. The code was written in summer 2015 and has been forgotten since; it took me another day to retrieve, re-run and update the code to make sure that it works in Solidworks 2017. Now I am finally ready to write an article, hoping it helps developers of all languages through technical issues I already underwent.

* You can download the source code and required files below from my GitHub repository.

First of all, you need to import references to the following two modules into your project:
Imports SolidWorks.Interop.sldworks
Imports SolidWorks.Interop.swconst
Actual files are located in C:\Program Files\Solidworks Corp\SolidWorks\api\redist. (your location might be different). Also, refer to this MDC article on the chamber geometry convention. Data structures and constructor compatible with the convention are given in lines up to 73. Lines 79~98 specify port geometry for my chamber which has two focal points. The variable 'FlangeOffsetDistance' represents the depth of the circular cutout to receive port tubing, measured from the face with knife-edge. Unfortunately I used meter units throughout so a lot of tiny sub-decimal-point numbers.

Main 'belly' of the chamber starts from line 146, in the order of: [1] 3d sketch [2] set a plane per port (this will be used for mating flanges in the later assembly stage) [3] main cylinder and port cylinders (solid cylinders at this point) [4] remove inner volume using shell operation for a specified shell thickness (you have to select EVERY circular faces for the shell operation to proceed as intended) [5] save parts file.

Line 226 and onward are for assembly. The code opens an empty assembly file, then load the above parts file, unfix it, place on the origin and properly align using planar coincident mates (lines 236~260). Note that the first part loaded into an assembly is set fixed, so you have to un-fix it first in order to move or re-orient it.  The three mates used here are deleted but don't need to be. Through lines 262~291 each flange file is opened, inserted into the assembly, and mated (x3). The grand assembly is saved once flange insertion is all over.

Note that the flange parts files were drawn from scratch by me, duplicating specs and CAD models available on MDC site. (There were reasons I decided to do these chores instead of using theirs but I forgot.)

Overall, the code should be straightforward and easy to understand; because it doesn't invoke any 'algorithm' per se, and because I inserted a few comments. One exception is the line 201, with comments in lines 202~ 204:
swPart.ShowNamedView2("", 8)
If any of the reference planes turns out to be oriented such that the plane normal is parallel to your monitor screen, or equivalently if any plane appears to be a line, the code fails to select the circle on that plane, and shell command will work only partially. Such coincidence can be avoided if one rotate the view orientation. Possible new orientation depends on a number of parameters including port geometry and your monitor specs. Switching to Trimetric in line 201 worked in my case but should not work in general.
swPart.Extension.SelectByID2("Top", "PLANE", 0, 0, 0, True, 1, Nothing, 0)
swPart.Extension.SelectByID2("Top Plane@" & FlangeTypeString(portschematic(i).FlangeType) & "flange-" & FlangeUsageCount(portschematic(i).FlangeType) & "@" & AssemblyTitle, "PLANE", 0, 0, 0, True, 1, Nothing, 0)
One other thing to note is the internal name of fundamental reference planes, potentially different Solidworks version by version. Solidworks 2014 uses "Top" but 2017 uses "Top Plane" for instance. I designed individual flanges with Solidworks 2014 but ran the above procedure in Solidworks 2017. That is the reason for the mixed notation in the code.

Words can't capture everything. You should have issues, or find unclear statements above. Please feel free to leave a comment.

Philips SAECO Xsmall espresso machine repaired

I have a SAECO Xsmall espresso machine. I bought it in Dec 2014, and brewed 2~3 cups of espresso per day on the average over the last 6 year...