Tuesday, 7 January 2014

IoT Rules: Event->Action versus State->State

A core difference between the Object Network approach to the IoT and every other that I've seen is in its programming model.


The Event-Action Programming Model

Other rule systems - or programming models within existing languages such as Javascript - are based on the Event-Action approach. This starts with an event, possibly coming from a subscription, such as "light level is now low", "owner is nearly home", "someone has entered the room", "switch has been turned off", "room is too hot", "it's turned night time", and so on. The rule matches such an event, then triggers an action: "turn on the light", "turn on the heating", etc.

This style is very simple and obvious, so does allow non-programmers to create rules quite easily.

However, it is very fine-grained, limited to simple parameters and actions. It very quickly hits a limit for more interesting programming of behaviour.

Having to model every input as a specific event, and every output as a specific action is not just low-level, but also highly prescriptive - your rules say "exactly in this case, you must do this".

In an environment of large numbers of independent but (hopefully) co-operating components, this can be a brittle model.

These approaches compound this because they usually have a central controller that expects all entities around to become slaves. Sometimes that controller is even outside of your own network.


The Object Network Programming Model

The Object Network programming model is more general and broad, and allows each Thing or object in the system to have complete autonomy.

In the Object Net, instead of events you have observed states, which may be complex descriptions of the whole of a Thing's current state, or even the current state of many linked Things, in your house or on the public Internet. Instead of actions you have new states for objects. Those new states may in turn be observed by other Things.

It is also a simple programming model, but a much more powerful one.

Every Thing or object is responsible for its own state, which depends on the state of other Things or objects around it, that it has links to:

When a light decides to observe a switch, it can set its own state to "on" when the switch's state is "on". Several lights could observe that switch state, or another state, and come on at the same time. Or another light can observe the first light and other lights around and set its own light levels to match them, or perhaps match their colours. The heating and lighting can observe the time of day and behave differently to other states of Things they are observing. A heater may refuse to turn on if some other state it is aware of, or rule it is following, is overriding it. A light can scan around to see if there's a light-level sensor that it can react to.

Nothing is run centrally, so Things and objects in the network just interact at their own pace and according to their own rules. Rules and states can be more like intentions than commands, allowing a more loosely-coupled federation of intelligent and interacting Things.

Further, much more context and surrounding state can be taken into account at once in those rules, because the rules have the entire local and global Object Network before them, on which to base their state transitions.


Monday, 6 January 2014

Open and Local, not Closed and Cloud

I came across this excellent article by T.Rob Wyatt yesterday. Go and read it..

OK, so if you didn't jump that link, here're some juicy quotes for you:

What is holding up the Internet of Things is that people do not want to buy devices that deeply penetrate their veil of personal privacy and then send fine-grained data about them back to device manufacturers.

And:

Screw in a Philips Hue bulb and all of a sudden that switch on the wall is worse than useless. You have to duct tape it in the “on” position to make the bulb fully functional and then are forced to use your phone to control the bulb. What LED “smart” bulbs need is a wall switch that passes power straight through but sends commands to the bulb using the API. 

And the Big One:

It is the open, local API that is missing from the Internet of Things.


Open and Local, not Closed and Cloud

Consider the Ninja Sphere - it depends on the remote servers to manage and run your rules.

Consider the British Gas Hive offering, which was splattered across Waterloo this morning:


Its website to control your heating is hosted by them, not you. British Gas gets to see every single heating adjustment you make, via the website or the app. And there's no API, at least not yet. Another app, another silo, another lock-in, another privacy leak.

The IoT will blossom once everyone just accepts the inevitable and opens up all their devices on the local network.

You should be able to choose a favourite way to see and control your home, office or factory, regardless of the provenance and technology of the sensors and actuators: the (single) app you like, the rule system you like. It should all just work together, with hardly any set-up, and not let in or out without you knowing and agreeing.

My Manifesto for the IoT describes this vision, and this blog documents my own explorations of it.

Obviously, I believe that one day everyone's favourite choice will be the NetMash app and NetMash servers, implementing the Object Network approach, programming in Cyrus rules.


And Finally..

Here's a nice bit of sloganising from the article by T.Rob:

Hardware is the new software.
Crowdfunding is the new VC.
Makers are the new kingmakers.




Sunday, 5 January 2014

Scanning BLE adverts from Linux

As I mentioned before, I need my Pies to be able to see each other's BLE adverts so that new Things can discover existing ones and find a place to belong to. I even suggested that a place could advertise itself directly, instead of jumping via a Thing object's "within:" link. That will be needed for the first Thing, at least.

Also, one day I'll want all my Pies to be scanning for mobile advertisers, such as people, robots, dogs and cars. Android currently can't itself be a beacon, but when it can, I'll need my Pies to be able to spot the app.

So I did a little research and came up with a possible answer. Unfortunately, as I said before, there doesn't seem to be a BLE API for Java yet, so we still have to call out to the command line. And the tools we have are apparently undocumented and rather clunky to use.


Clunky Method

First you kick off hcidump:

root@duncan-dell/0:~ -> jobs
[1]  + Running                       hcidump -x -R

You need "-R" to show the raw data and "-x" for hex dumping.

Now call "lescan", and watch the output of hcidump:

root@duncan-dell/0:~ -> hcitool lescan > & out

The following is the output of hcidump:

< 01 0B 20 07 01 10 00 10 00 00 00 
> 04 0E 04 01 0B 20 00 

Don't know what that is.

< 01 0C 20 02 01 01 
> 04 0E 04 01 0C 20 00 

Or that.

> 04 3E 2A 02 01 03 00 B3 F1 C6 72 02 00 1E 02 01 1A 1A FF 4C 
  00 02 15 C0 A8 00 12 1F 92 B5 0D C3 24 A3 7F 7A 66 00 00 00 
  00 00 00 00 C2 
> 04 3E 2A 02 01 03 00 87 6C C8 72 02 00 1E 02 01 1A 1A FF 4C 
  00 02 15 C0 A8 00 11 1F 92 4B CF D9 1F 26 0E F6 E2 00 00 00 
  00 00 00 00 BC 

Aha! There're my two Pies. I've highlighted the MAC number, which is reversed. The hex following is our advertising data, containing the URLs.

Interestingly, the last octet of the data has a number there. I did some tests to see if that was the RSSI, but it didn't seem to change in any correlation to the distance. The "1E" after the MAC tells us that there are 30 octets following, which does indeed fall one short of the end. More on this below.

It then hangs, presumably continuing to scan. When you kill it, hcidump splutters a bit:

< 01 0C 20 02 00 01 
> 04 0E 04 01 0C 20 00 

Here's the rather uninteresting output saved by the actual lescan command:

root@duncan-dell/0:~ -> cat out
LE Scan ...
00:02:72:C6:F1:B3 (unknown)
00:02:72:C8:6C:87 (unknown)

I believe that "unknown" refers to the fact that it found the "FF", or manufacturer-specific data, in the octet string. See below for more on that.


RSSI?

In pursuit of the RSSI, I ran hcidump without the raw mode flag and got more promising-looking output:

< HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7
    type 0x01 (active)
    interval 10.000ms window 10.000ms
    own address: 0x00 (Public) policy: All
> HCI Event: Command Complete (0x0e) plen 4
    LE Set Scan Parameters (0x08|0x000b) ncmd 1
    status 0x00

Ah! So that's what that meant.

< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2
    value 0x01 (scanning enabled)
    filter duplicates 0x01 (enabled)
> HCI Event: Command Complete (0x0e) plen 4
    LE Set Scan Enable (0x08|0x000c) ncmd 1
    status 0x00

Uh-huh..

> HCI Event: LE Meta Event (0x3e) plen 42
    LE Advertising Report
      ADV_NONCONN_IND - Non connectable undirected advertising (3)
      bdaddr 00:02:72:C8:6C:87 (Public)
      Flags: 0x1a
      Unknown type 0xff with 25 bytes data
      RSSI: -62
> HCI Event: LE Meta Event (0x3e) plen 42
    LE Advertising Report
      ADV_NONCONN_IND - Non connectable undirected advertising (3)
      bdaddr 00:02:72:C6:F1:B3 (Public)
      Flags: 0x1a
      Unknown type 0xff with 25 bytes data
      RSSI: -68

There's the supposed RSSI, then - but it's the same as that "random" octet - and it similarly doesn't change even when I press the Pi right up against the laptop BLE.

Notice the bit where it says it doesn't understand all this Apple-ese (0xff).

< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2
    value 0x00 (scanning disabled)
    filter duplicates 0x01 (enabled)
> HCI Event: Command Complete (0x0e) plen 4
    LE Set Scan Enable (0x08|0x000c) ncmd 1
    status 0x00

Killing the lescan.

This is all extremely clunky, but can be made to work, as long as I find out what's up with the RSSI. Someone else had the same issue it seems. I can at least set up the light object place links this way instead of hard-coding them.



Saturday, 4 January 2014

Three Lights in Three D Place!

I added two more rules. The first rule is in a light Thing/object to notify to its place that it's there. The link to the place is hard-coded for now until we get mutual discovery. The second rule is in the place and rather simplistically just adds any notified object at a fairly random location.

Here's what the Android app can then see, after starting up the place, then starting up the Pies - the three lights from yesterday, all automatically notified to, and located in the place object:


As you can see, I've touched them to set their colours. The actual LED behind one of them also changes, of course.

Next job is to advertise this place object instead of the third light, on my laptop. I've currently set a hard-coded URL and UID in the server and the Android app, but it should be auto-generated, like the light UIDs. Then I can get the lights to place themselves there - if they can somehow be coded to see BLE adverts like the Android app can.

Oh - that mysterious dark object in the background is a pretend light level sensor. When you set its light level below 100, all the lights come on white. This is the rule, which I discussed before. Eventually I hope to wire this into a Pi camera, which should be able to detect light levels, colour temperature and motion in a room.


Friday, 3 January 2014

Three Lights!

Well, progress is slow but steady. Now that I've identified each light Thing separately and am broadcasting unique URLs from my Java code, I've updated the Android app to list them all, unlike before when I just had one.

I gave them all the same name - "Light" - so this screen shot is kinda boring, but you get the idea:


This is picking up three BLE beacon broadcast URLs from two Pies and from my laptop. Jumping the link shows a different light running on that respective host. One of them actually changes the LED colour.

Next job is to put them all in a "place" object so I can "walk around" virtually in 3D and set their light colours. I'll get the laptop to broadcast a place object instead of a light, and have the Pies be two lights in that place.

Each has a signal strength, so once that's done, I'll be onto the AR algorithms for location and orientation, so that I can really walk around to get to them.

Thursday, 2 January 2014

Nexus 4 conflict between WiFi and Bluetooth

I mentioned the other day how my Nexus 4 wouldn't allow me to use both Bluetooth and WiFi at the same time.

Well I did a little research, and found this issue describing the  problem.

Solutions may be: to use a different WiFi channel setting, or to switch to 5GHz. I'm using 11g currently, but I'll try 11n. Which I should be doing anyway, I guess.

I'll try these out and report back..

Update: I've no idea if it's using 5GHz or how to find out, but using 11n does seem to be working...

Wednesday, 1 January 2014

Java BLE broadcast

Finally got some Java code into NetMash to drive the BLE URL broadcasting today, instead of manually typing it into the command line.

Here it is, in case you're interested:

    void startBroadcasting(){
        byte[] ipbytes=UID.IP().getAddress();
        int port=Kernel.config.intPathN("network:port");
        String re="uid-([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])-([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])-([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])-([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])";
        Matcher m = Pattern.compile(re).matcher(uid);
        if(!m.matches()) return;
        String advert="hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 ";
        advert=advert+String.format("%02x %02x %02x %02x %02x %02x %s %s %s %s %s %s %s %s ",
                 ipbytes[0], ipbytes[1], ipbytes[2], ipbytes[3],
                 port/256, port-((port/256)*256),
                 m.group(1), m.group(2),m.group(3), m.group(4), m.group(5),  m.group(6), m.group(7), m.group(8));
        advert=advert+"00 00 00 00 00 00 00 00";
        exec("hciconfig hci0 up");
        exec(advert);
        exec("hciconfig hci0 leadv 3");
        exec(advert); // possible bug workaround
    }

    void exec(String command){ try{
        Process p=Runtime.getRuntime().exec(command);
        BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
        int read;
        do{ read = bis.read(); }while(read != -1);
    }catch(Throwable t){ t.printStackTrace(); }}

Not pretty, but seems to work - there's a strange bug I haven't tracked down the cause of, which seems to be fixed by setting the advert data twice as you can see above.

This works on both my Pies, but the Android code is still too dumb to show them both. So that's my next task, plus showing the approximate distance between the phone and the Pies.