Subscribe via RSS
23Jun/150

My Pebble Time has arrived

I've always thought a smartwatch would be fun, but I've never really been keen on any of the models available. This stood true until I found out about the Pebble. The previous models were butt-ugly, but the kickstarter project for the Pebble Time took my fancy.

time-banner

I backed the project and received my Pebble Time last Thursday. The contents of the package were very simple: A manual/quickstart, a charging cable and the watch itself. The watch came pre-charged and I was ready to plug it in.

open-box

Initiating Connection

first-bootI enabled bluetooth on my phone and loaded up the Pebble App. It found the watch and then tried to update it's firmware. This managed to fail 3 times in a row... I held down a number of buttons on the watch but could not get it to reboot as per their recommendation. On the fourth attempt, the firmware updated.

I could now view the installed watchfaces and apps on my watch. Watchfaces are apps, but they get maximum screentime as they're the default app shown, displaying the time. Extra Apps can then be installed to do any number of tasks. The watch is effectively always connected to the world, as long as your phone is... and as long as you have battery... everywhere.

First Impressions

The battery life is intense. It lasts around 5 days without charging. It's warned me today that it's at 20%, but I thought I'd keep going to see how long it lasts. Last charge was Thursday evening. Better to deep-cycle the batteries, I suppose.

Off the shelf there is a remote to control music, an app to configure alarms (not tied in to any Android app), watchface selection and settings. The Music remote works great, although it tied in to 'Apollo' instead of Google Music... I have no music in Apollo.. will need to sort that out.

There's a whole plethora of watchfaces to install. Anything you can think of. I tried WeatherLand and IsoTime, two great designs. The former takes into account your location and the local weather and renders the background mountain scene accordingly! There's also the shadow clock, which is installed by default.

IMG 20150623 135216 IMG 20150623 135304 IMG 20150623 135457

I haven't installed any third-party Apps on the watch yet... I'll do that and report back here... but I have gone ahead and created my own custom Watchface!

Cloudpebble and Developing

Development for the watch couldn't be easier. Browse to Cloudpebble, create an account and you're already set to go. You can program in C++ or Javascript via their online IDE, which works extremely well. It can even allow you to emulate a watch via the web or directly upload your project to your own watch via your phone! The upload works via your phone's internet connection and then bluetooth... just enable Developer Mode in settings and you're off.

You can choose to develop an App or a Watchface. These are really the same thing, but a watchface will be categorised correctly and perform the correct actions on button-press events.

Mimicking My Old Arnette Watch

old-arnetteHere it is... it was a clunker and it contributed to a broken wrist. (Don't wear watches whilst playing sport!) This is the last remaining photo I have of this model and it is near-on impossible to find any reference to it on the internets.

As you can see, my watch bit the dust after a decade of punishment. I had loved the 'text mode' so much that I decided to emulate it on the Pebble Time. I used FontStruct to create a 30px high font that resembled the Arnette font. This then worked perfectly as a resource in cloudpebble and rendered pixel-for-pixel on the watch itself.

I then just had to write the logic to write out the text of the time. This was a little tricky, but nothing that couldn't be solved by a few arbitrary values and if clauses. The result speaks for itself! There was the odd bug or two to start with... but I've been testing the watchface out in the field and it's working great. I think I might add a battery meter on there and a few other doo-dads if possible. I'll then release it to the greater community.

Note that the old Arnette actually had a 'magic-a-ball' if you held down the top-right button. I hadn't known about this feature... 4 years in to owning the watch I accidently held down the button whilst trying to set the time and the friggen a-ball came up. It read back to me "YEAH SURE". Nice fortune! After that it became a great decision-maker whilst intoxicated. I might also program this into the watchface... will need to work out if I can commandeer the buttons whilst in 'watchface-mode'.

IMG 20150623 123045 IMG 20150623 123204 IMG 20150623 130328
IMG 20150623 130509 IMG 20150623 134455 IMG 20150623 141354

In the last shot you can see that I realised I'd had the colours the wrong way around... flipping them gave me goose-bumps... although the screen is 4x the DPI of the original watch, the result is so similar it's not funny. I love it!

Got any other ideas/development requests?

Feel free to leave a comment here and request something custom for this watch? Am happy to work with anyone who wants to design/develop something for this watch. It's a great platform and the only limit would be one's imagination!

28May/150

An insight into the workings of a Comment Bot

I get emails every now and then from this blog telling me that there's a new comment for approval. Most often than not, it's spam. It's also usually really shit spam. The context is wrong, the URLs are Russian and the text is crap. I have always wondered how it's generated and who would be the one posting the comments.

Regardless of the plugins I have enabled to stop spam (and it seems 10000s of comments are in fact stopped), some of the crap still gets through.

Today I received an email indicating a new comment. This one was different though... the contents seem to have been verbatim pasted, as opposed to 'customised' by the 'poster'.

{I have|I've} been {surfing|browsing} online more than {three|3|2|4} hours today, yet I never found any interesting article like yours.
{It's|It is} pretty worth enough for me. {In my opinion|Personally|In my view}, if all {webmasters|site owners|website owners|web owners} and bloggers made good content as you did, the {internet|net|web} will be {much more|a lot more} useful than ever before.
I {couldn't|could not} {resist|refrain from} commenting.

{Very well|Perfectly|Well|Exceptionally well} written!
{I will|I'll} {right away|immediately} {take hold of|grab|clutch|grasp|seize|snatch} your {rss|rss feed} as I {can not|can't} {in finding|find|to find} your {email|e-mail} subscription {link|hyperlink} or {newsletter|e-newsletter} service. Do {you have|you've} any?
{Please|Kindly} {allow|permit|let} me {realize|recognize|understand|recognise|know} {so that|in order that} I {may just|may|could} subscribe.
Thanks.
{It is|It's} {appropriate|perfect|the best} time to make some plans for the future and {it is|it's} time to be happy.
{I have|I've} read this post and if I could I {want to|wish to|desire to} suggest you {few|some} interesting things or {advice|suggestions|tips}.
{Perhaps|Maybe} you {could|can} write next articles referring to this article.

Woah... it seems that these comments really do get customised... I mean, they still have NOTHING to do with my blog and the URLs they point to have NOTHING to do with the guts of the comment, but the contents of the comments seem to be variable.

I assume the variability is to prevent the crap getting marked as spam. The English makes sense, to the point where each of the permutations actually sound like a native speaker.

I wonder if a bot chooses, at random, which word to use from each array, or if a human is doing it all. A human should, at least, know that the entire body has nothing to do with any post on this blog; but then again, the poster may not even speak English.

I am sure this {article|post|piece of writing|paragraph} has touched all the internet {users|people|viewers|visitors}, its really really {nice|pleasant|good|fastidious} {article|post|piece of writing|paragraph} on building up new
{blog|weblog|webpage|website|web site}.
Wow, this {article|post|piece of writing|paragraph} is {nice|pleasant|good|fastidious}, my {sister|younger sister} is analyzing {such|these|these kinds of} things, {so|thus|therefore} I am going to {tell|inform|let know|convey} her.
{Saved as a favorite|bookmarked!!}, {I really like|I like|I love} {your blog|your site|your web site|your website}!

Then again.. if you keep reading the dribble you'll see how crap it is and, even though some sentences flow, others just don't belong where they are.

Meh... either way, it was a very interesting insight into the workings of these bots/humans/drones posting shitty comments on the world of blogging.

28May/150

Sockets: Bytes and Message Terminators

Sockets are fun. They're a cross-platform mechanism for opening a black hole to another dimension. Of course, you're the one that defines the other end and you're in full control of what gets sent into the hole.

Hopefully you've also written the code at the other end... that way you're also in full control of what comes back through the hole. Note that, like any good black hole, the specks of data flying back at you won't always be complete, nor in sequence. Fortunately, if you're using TCP, the underlying network technology/code will rearrange the packets for you. UDP, on the other hand, will send the packets to you as it receives them.

Text or Bytes?

It does get better though... especially when you're trying to send through real data, we'll call them bytes [valued from 0 to 255], as opposed to just fancy textual strings in the ASCII format. The latter is great if you actually want to send legible messages; a chat program perhaps? But useless if you want to send large numbers or other binary data quickly and efficiently.

A quick example... say you want to send the value of a HTML colour. Let's choose the colour off-white, of RGB value (250,250,250). You could send the string "250,250,250" and the receiver could parse the ASCII values. You could save further chars by passing in "250250250" and, as long as your receiver understands the format, it would still be understood. What you need to realise though is that you're sending 3 bytes down the pipe when you really only need to send one. Each byte, in this case '2', '5' and '0' are all bytes, has the ability to store a numeric value from 0 through to 255.

The first byte, the ASCII character '2' is actually represented by the numeric raw value 50. The basic idea is that ASCII is a big lookup table. The number 20 is the index in the table that describes the pixel arrangement to display a character '2' on the screen. What you can then realise is that, in the buffer, you've actually placed the value 50 in the first byte, not 2. If you knew how to read that value as 50 and not 2, then you're already saving 1 byte (as '50' would take two ASCII characters!)

It gets better though... each byte can store up to the value 255, so instead of trying to jam the string "250" into three bytes, you simply need to store the value 250 into the first byte.

Signed or Unsigned?

A byte has 8 bits. Of these 8 bits, all 0s equals the numerical value zero and all 1s equals 255. You can therefore store 256 values in a byte. Computers, to represent negative numbers, use the most significant bit (determined by endianess) as a flag to indicate if a number is negative. Unfortunately, this takes one bit off your value, allowing you to store -128 to +127. Why not -127? That would be a waste and would allow -0 and +0. See Two's complement to understand more.

In the end, unless you're using C# (where Microsoft likes to 'help' you and limit ASCII usage) then it'll be up to the receiving end as to how to read the data. All the bits will be there; it's just a matter of casting them to a format you desire.

Message Terminators

Firstly, I'm using the term 'message' here to describe a block of data sent from the server to a client. This block is formulated by the server with known start and end indicators and thrown down the tubes. If the client isn't listening hard enough, then they may well miss the start of the message and have no idea how to recover and process the rest of the data. The goal is to create unique tokens in your message stream to allow a client to truncate data it can't deal with and get back to a known starting point. It can then process the next message in the queue.

Choosing a terminator can be difficult. A unique byte, or sequence of bytes, can be hard to determine if you are expecting to send arbitrary data in the message content. Human-readable characters can be used, if sending strings where those characters can't possibly be included. The 'pipe' | is a good choice, even a comma if you're in total control of message content and can replace/remove them from the middle. The issue will be that as soon as a terminating character is found in the middle of the string, then the client will expect that the message is complete and pass on the truncated data for further processing. It then gets worse when the client retrieves the next message which happens to be the second half of what should have been a complete message.

The best way to get around this is to have a header at the start of your messages. First and foremost this header needs to indicate the length of the message it describes. From then on you can have whatever message content you want, making sure the byte count matches the length you have set. In a recent application, I limited myself to 255 byte messages, so the first byte of any data sent was a numeric value that describe the number of following bytes that made up the message. I then also put a terminating character at the end, the pipe, as a check so the client could confirm that the end was really there.

Putting it all together...

Once you've defined a message structure, your listeners and receivers should be able to decipher the string of bytes coming down the line with a little more ease. Of course, if they get caught up and fail to read packets then those packets are lost. Your next step would be to ensure each end is in a known state and that if a state hasn't progressed that data needs to be re-sent.

I'll post again in the future with code samples for the theories above.

7May/150

net.tcp and IIS Express does not work

I've just spent time trying to rig up a test to get a working net.tcp server. Turns out that, in Visual Studio 2012 (and just about every other VS version), the IIS Express Server that one usually debugs through CANNOT support anything other than HTTPS and HTTP.

Q: Does IIS Express support non-HTTP protocols such as net.tcp or MSMQ?
A: No. IIS Express only supports HTTP and HTTPS as its protocol.

Please do not waste your time... When you hit debug on your net.tcp service, IIS Express will instantiate and you'll be thrown to your favourite web browser, staring at your root folder which is readable. You'll note that you'll also be on a port that has nothing to do with your web.config. This is because IIS Express has generated a random port and not cared one iota for your port configurations in web.config. You'll get nothing but connection refused when you try to connect to net.tcp://localhost:PORT/Service.

I was about to whinge that this tutorial on configuring a net.tcp service on IIS7 doesn't mention anything about incompatibilities with IIS Express. I suppose that one must assume by the header that the article is only for IIS7. A footnote would still be greatly appreciated for those trying to develop their code before deploying it!

If you ever want to get this to work, deploy and test your server on a real IIS instance and run from there... IIS7 preferably.

Note, if you need to debug... bring the server up, hit it with a simple query to make sure the app pool is active, and use Debug -> Attach to Process from Visual Studio. You'll find w3wp.exe way down the list with your Website's 'name' next to it. Highlight it and hit Attach to debug pesky server-side problems.

Once debugging in Visual Studio, you'll then need to open your source files (they can be in any folder, VS initially wont find them automatically) to set breakpoints. Note that exceptions will be caught in VS whilst debugging and will halt execution on IIS for all users. I have, once or twice, accidentally left the debugger attached overnight and had very angry clients in the morning with stalled connections.

5May/150

FileSystemWatcher isn’t watching your files?

Quick note that just stole 2 hours of my weekend; of which I'll never get back... It seems that the FileSystemWatcher in C# it capable of watching files... yes.... but it turns out that the filters aren't as simple as you'd think.

Say you want to watch for new or changed text files in a folder? Filter = "*.txt" right? And the folder has a crapload of *.txt files? that's how it displays in Explorer? Right?

Wrong... Check out this sample code... yes, I'm holding the files open in my own source, but this is just a dirty way to show what's happening:

        static void Main(string[] args) {
            string folder = @"d:\temp\fileWatcherFolder\";
            FileSystemWatcher fsw = new FileSystemWatcher(folder, "*.txt");
            fsw.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.LastAccess;
            fsw.Changed += fsw_Changed;
            fsw.EnableRaisingEvents = true;
            using (StreamWriter file = new StreamWriter(folder + "test5.txt")) {
                Console.WriteLine("[");
                for (int i = 0; i < 10; i++) {
                    file.WriteLine("test line " + i);
                    Console.WriteLine(".");
                    Thread.Sleep(1000);
                }
                Console.WriteLine("]");
            }
            Console.ReadKey();
        }
        static void fsw_Changed(object sender, FileSystemEventArgs e) {
            Console.WriteLine(e.Name + " was changed!");
        }

From above, you can see that I start a watcher on a known folder, I then start a new file and write to it. The output should always show that updates are occurring. The updates never come... and this is symptomatic of what I had with another external application that was holding files open. It also then presented a bigger issue of adding tildes to the end of the extensions.

It seems that this is an issue in .NET regarding file flushing. The application with the file handles open must flush the data out for a FileSystemWatcher to pick it up. Depending on the speed and quantity of files being flushed, the watcher may have to be customised to cope with the load. Check out the InternalBufferSize parameter.

Note in the above code, you can force a file.Flush() after the file.WriteLine, you'll get a single event. If you use file.FlushAsync() then you'll get ALL of the events! There is no threading in my example code, so the fact that async works makes sense. Of course, if you have no control over the application that is writing the files (as I didn't) then you're stuck trying your hardest to watch the files.

I still can't see my files?!

It gets better though... on some versions of windows, you may will not even see the filename with the expected extension... there may actually be a tilde at the end of the name... invisible to the naked eye. Explorer will show "test5.txt" but the watcher will see "test5.txt~"! It seems that if another application has the file open, the operating system keeps the filename with a tilde at the end until 'flushed' to disk. I haven't been able to reproduce this via the source above, using notepad to hold files open... but I know it happens. The application I had to deal with spewed files out quickly, holding them open, and the watcher only saw "txt~" extensions...

If this is the case, then you can loosen your filter to "*.txt*". Note that if you have a LOT of files being created, then this will slow down the watcher considerably. I actually recommend that you set up a second watcher, one for "*.txt" and the other for "*.txt~".

It's only when you watch the files with a filter of *.* that you'll see the crappy extension names. So when trying to debug this... set your filter as 'relaxed' as possible to capture changes and tighten it when you know what you are looking for.

Be careful! It seems others have had the same problems: FileSystemWatcher class does not fire Change events when NotifyFilters.Size is used.

17Apr/150

Migrated WordPress database; Theme mods are gone!

This was fun... I just helped a friend migrate their database. The DB export and import was fine; just don't try and paste the SQL into the query window all at once... go to the import page on PHPMyAdmin and upload it there!

Meanwhile, once uploaded, all the custom settings on the themes (it inherited from a base theme) were lost! I watched the database and the fields were actually reset! There must have been an error parsing the data. It has to be noted that I had to change data in the database during the migration. As that I was changing from one domain to another, the hard-coded URLs needed to be migrated.

In the source database, the row in the wp_options table with key 'theme_mods_Divi' looked like this:

a:8:{
     i:0;b:0;s:30:"et_pb_predefined_layouts_added";s:2:"on";
     s:36:"et_pb_predefined_layouts_updated_2_0";
     s:2:"on";s:16:"background_color";s:6:"ffffff";
     s:49:"http://old_domain.com/images/background_image.jpg";s:17:"background_repeat";
}

I don't know what the first a:8 stands for, but all the s values inside mean string, followed by the length, then the data.

I actually, as a migration task, had to change the strings from one URL to another (as part of the domain shift.) Turns out that when you do this, if the URLs being replaced aren't the exact length, then the string lengths will change .... of course, this is obvious now .... WordPress was then trying to parse the values and overrunning/underrunning the values. In the end it just gives up and resets the custom mods.

So, when changing the strings, you need to change something like:

s:49:"http://old_domain.com/images/background_image.jpg";

to:

s:62:"http://google_is_the_best.com/images/zebra_in_a_tree_image.jpg";

...the key being that you've adjusted the length to the new variable.

Once this is done: drop all the tables, re-import them via the script and WordPress should then load the mods correctly! I hope this prevents at least one other person from wasting the 2 hours that I just did. Never lose your custom theme settings/mods when migrating ever again!

5Mar/150

A quick note on interfacing with JSON services via C#

I'm sure there are 100s of ways to manually create classes for JSON objects and then decipher them upon web-service response, but I've just stumbled across a fantastic site called 'json 2 csharp' that creates the classes for you. Just slap in your response (try to get a fully-fleshed out one with as fewer nulls as possible) and it'll generate the class structure.

You can then use the NewtonSoft JsonConvert deserialiser to populate it.

An example

Here's a link: jsontest 'date' example. It produces the following response:

{
   "time": "05:13:02 AM",
   "milliseconds_since_epoch": 1425532382121,
   "date": "03-05-2015"
}

From here, you just copy the entire response and paste it into the text field on the json2csharp site.
Hit 'Generate' and the site will spit out the following:

public class RootObject //rename this!
{
    public string time { get; set; }
    public long milliseconds_since_epoch { get; set; }
    public string date { get; set; }
}

Note that 'RootObject' is a little boring... rename it to 'DateResponse'

Add a helper library to your code to easily pull JSON responses (and POST):

public static class JSONUtilities
{
	public static string GetJSON(string url)
	{
		HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
		try
		{
			WebResponse response = request.GetResponse();
			using (Stream responseStream = response.GetResponseStream())
			{
				StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
				return reader.ReadToEnd();
			}
		}
		catch (WebException ex)
		{
			WebResponse errorResponse = ex.Response;
			using (Stream responseStream = errorResponse.GetResponseStream())
			{
				StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
				Console.WriteLine(reader.ReadToEnd());
			}
			throw;
		}
	}

	public static Tuple<HttpStatusCode, String> PostJSON(string url, string jsonContent)
	{
		HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
		request.Method = "POST";

		System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
		Byte[] byteArray = encoding.GetBytes(jsonContent);

		request.ContentLength = byteArray.Length;
		request.ContentType = @"application/json";

		using (Stream dataStream = request.GetRequestStream())
		{
			dataStream.Write(byteArray, 0, byteArray.Length);
		}
		long length = 0;
		try
		{
			using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
			{
				length = response.ContentLength;
				using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
				{
					return new Tuple<HttpStatusCode, string>(response.StatusCode, reader.ReadToEnd());
				}
			}
		}
		catch (WebException ex)
		{
			// Log exception and throw as for GET example above
			Console.WriteLine("ERROR: " + ex.Message);
			throw ex;
		}
	}
}

And now you can bring it all together:

private bool Get()
{
    var result = JSONUtilities.GetJSON("http://date.jsontest.com/");
    var dateResponse = JsonConvert.DeserializeObject<DateResponse>(result);
    Console.WriteLine("Got Response: " + dateResponse.date + " [" + dateResponse.time + "]");
}

Too easy!

7Jun/130

Misfiring AW11 4AGZE Supercharger

Just got my car back from the mechanic... he does a really good job, but I'll leave the name out of it for all intents and purposes.
Turns out I'd done too much off-roading in my poor little MR2 and had filled the engine bay with dirt/dust/grime. Mechanic took the liberty to wash it all out... looks great!

Unfortunately, it didn't run so good anymore.

Symptom

Upon acceleration, the tacho would get to 1,500rpm and then it felt like the rev-limiter kicked in. The engine would burst about 100rpm, then drop back to 1,500, then back up and down, on and off.

It felt terrible to drive... if you timed it right, you could stop accelerating at 1,459rpm then gun it and it'd jump to 2,000rpm and continue... BUT THE SUPERCHARGER LIGHT STAYED OFF.

Something had gotten into the wiring and was going haywire. Stopped the car, got a torch and checked everything. All was connected apart from a cracked up vacuum tube. Thought it was the culprit, but upon sealing the connection it was still failing.

20130607 174807

I could see the supercharger clutch engaging when I feathered the throttle, but it would pop back out just as quick when the engine dropped revs.

So... resorted to Google and found this: http://forums.club4ag.com/zerothread?id=89527
Reading the second post, the user indicates that the TPS was causing his engine to start/fail/start/fail... same symptom as mine.

So, went back to the engine and popped off the TPS connector.

20130607 181739

FULL OF WATER.

Solution

Dried it up and ... the MR2 is back to bat-out-of-hell status... I love my little green Supercharger light!

I'm only posting this so that other people can find this information easier.

9Feb/120

OpenLCB: Controlling Your Model Railroad

It's been a while since anything remotely home-brew/electronic for model railways has appeared on this blog... but this is about to change. It's now time to try a third method of electronic control after previous attempts of controlling via DCC Boosters and then Arduino Microprocessors.

Don E. Goodman-Wilson, who you would've seen commenting on a few of my posts here regarding DCC and Arduino, has gone all-out and started production of some pretty amazing technology. He's started a company called railstars which is currently providing DCC boosters, central units and throttles. Not only are these perfectly marketed and designed, they also now incorporate a new concept known as OpenLCB.

OpenLCB

OpenLCB is an initiative by the OpenLCB team to define a network (protocol and required hardware) to control pretty much everything on your model railway. The end result is layout control and automation which is easy to install, configure and extend. As of the 9th of February 2012, there are motions for NMRA to work closely with the OpenLCB project in a venture named NMRAnet... stay tuned for more information on that!

It should be noted that the OpenLCB team is still in the early stages of design work and, although prototypes have been built and tested, there is a lot of work to do to get final products to market.

The basic concept consists of a control bus with nodes located along a network bus, terminated at each end. Each node has it's own processor that can create and respond to events. Events can be anything from controlling accessories and trains on your layout to sending informational messages to remote displays. With this, you can have a node controlling points around your layout, a node controlling trains indirectly via DCC and a final node acting as a control panel with buttons and switches configured to send specific events.

In case you were wondering, the OpenLCB venture has no intention to interact with DCC. Other parties, such as Don with his railstars products, are currently bringing DCC in as an option, but do not intend to outright replace it! Don's efforts with railstars OpenLCB components will allow DCC commands to be transmitted over the OpenLCB protocol allowing each node on the network to respond appropriately. A lot of opportunities will open up with this as you will then be able to use the OpenLCB network to transmit DCC information, allowing completely separate DCC blocks on your layout.

You can find a lot more information about OpenLCB here at their 'First Look' page.

I want to control my DC Layout?

There are currently no nodes designed for use as standard DC throttles; fortunately, controlling DC layouts via the OpenLCB bus should be completely feasible! As per my previous articles on Arduino control of model railways, a simple PWM motor controller is all that is required to supply a model railway with the appropriate power levels. Since OpenLCB is also very compatible with Arduino, it would also therefore be quite practical to transform an Arduino+Motor Controller into an OpenLCB 'node'. This would mean that any 'controller node' could then send 'events' to the 'pwm node' which would then act accordingly... be that 'supply 50% throttle'.

I'd spoken to Don on this concept and he indicated that the OpenLCB key concept was to control 'Trains' rather than 'Blocks'. This is the same as DCC... as you supply the same power+data to all rails on your layout and the locomotives respond only when called. The issue then with DC control is that trains, sitting in blocks, will respond as soon as you apply power. One answer would be to have detection circuits around the layout which would follow movement and assume where each train was. Another would be to have the 'pwm nodes' act simply as 'accessories' that supply power to each block. This concept is still under discussion.

What's Next...

I really do want to get into development and testing of the OpenLCB system. Fortunately the whole lot is open source and one can even use standard Arduinos as 'nodes' based on the code available in the OpenLCB repository. Once I have enough components I'll be building and connecting a few nodes to test the communications functionality. After that I'll go ahead and design a block-controller and pwm node. At the least this will allow me to prototype some ideas whilst controlling my latest n-scale-in-a-table layout.

The OpenLCB project will also shortly be offering a 'dev kit' to parties interested in developing for the OpenLCB project. It will have enough components to create a local network able to control a layout. You can find out more information on the Japanese Modelling & Japan Rail Enthusiasts Forum.

I intend on keeping everyone updated as I tackle the concept of DC in the newly formed OpenLCB realm.

28Sep/110

Ruby on Rails – Disturbing Errors

Excuse my efforts in going slightly off topic in an attempt to help out anyone else who may have struck this issue.
I'd been given a good challenge by a friend: mimic an install of ruby on rails on a local VM. I'd never worked with ruby before and google'd for a tutorial. Before I knew it I had Turnkey Linux's Ruby Appliance up and running on Oracle's Virtual Box on 64-Bit Windows 7.

I wont go in to deployment steps here... it's all covered on the web. The basic concepts were to point an apache virtual host at a new directory in /var/www and then browse to the application. To my delight it started, throwing an error. I hadn't even configured a thing yet, so how could I expect it to run?

After configuring the Facebook connector and the database connection the site came up and I could log in and muck around. It wasn't long until I hit the following error. It was only on a specific data class that extended the ActiveRecord interface and only when checking if the data was valid or trying to save it. I could happily create the class and change attributes...

Wrong number of arguments (1 of 0)

What the hell... I hadn't seen ruby exceptions before, so I started to dig. The RAILS_ENV environment variable was set to 'development' and so there was a 'development.log' file sitting in the 'log' directory inside the application. This provided a stack trace and a few other bits and pieces.

After a lot of code commenting and uncommenting I narrowed it down to the 'save' method of the specific data item class. This was inherited from the ActiveRecord::base class and I had no say in what it did or how it did it. I did know that it was expecting no arguments, so that's where the '0' came from in the error, but I was also not passing it any arguments, so where the hell did the '1' come from!?!?!

I then tried the 'valid?' call as well... same result.

I chose to override the 'save' function in the model file by using a pass through... all of a sudden the code continued (after hours of exceptions) and the next related table row creation had a null foreign key for the item that should have been saved. It turns out that by creating a pass through I bypassed the entire 'save' method and therefore didn't attempt to write anything to the db. As soon as I tried to use the base 'save'I got the same error but now in the model file.

I was stuck... so I tried to bring up the debugger via the mini WEBrick server. It, unfortunately, didn't give me any more information than what the development.log file had provided.

Next I tried downgrading and upgrading ruby and rails. I was impressed with the 'gem' system... but nothing helped.

The final step was to google more and more... I had already tried gutting my model implementation (there was extra code in the for other tasks) but none of this changed the inability to call 'save'. All of a sudden one google search came across someone mentioning something about a 'reserved word'.... I google'd further.

Reserved Words

It seems that Ruby has a few words that you MUST NOT GO NEAR if you want your code to work. The main issue is that, when you do, you'll have no idea what you have done as the error message that results has NOTHING TO DO WITH the actual problem. It turns out that after browsing to a post by someone with a similar problem I saw the comment stating that they had used the word 'notify' for a column name.

... so had the original developer of the code I had worked on ...

There was no response to the post that pointed this out in the previous link, so that either means the original author was too ashamed and it was the correct fix, or they found the real fix and never got back to this.

Either way, I corrected my database by changing 'notify' to 'notify_opp' and ... fkn presto ... 10 hours of debugging resulted in a SUCCESS!

Further information on these magical reserved creatures

Ok, the fun part... in hind-sight I've done a little research and there are sites indicating what 'words' are 'reserved' for ruby. Unfortunately, not all of them say that 'notify' is!

References:

Conclusion

Be bloody careful with errors from ruby that don't make sense and don't spend too long digging in to a dead end.
Be diligent with your google searches too.

I spent a lot of time debugging this and I hope this post helps out others in the same scenario.