Wednesday, February 8, 2017

Fire OS's Permission Problem


I own an Amazon Fire HD 8 tablet. It was so cheap, I certainly got my money's worth. But it does have some problems. The above screenshot illustrates one. This is an alarming set of permissions that are necessary to install this app (there are many more that don't fit on the screen). "Generic permissions access" sounds particularly alarming. Many many apps in the Amazon App Store and the Google Play store (which can be installed on the Fire with minimal fuss) have extensive lists of permissions, and the app descriptions generally contain no justification of this permission use.

Here's what it looks like when trying to install the Nest app (owned by Google) from the Google Play store on Fire OS:

The blame should really be shared between Google and Amazon: Google, for taking so long to get its act together on how users grant permissions to apps (Google didn't fix this until Android 6, Marshmallow.), and Amazon, for basing the latest version of Fire OS on Android 5, Lollipop.

Apple should get the most credit here, because they got it right first. For as long as I've owned an iPhone, I'm never been asked to grant permission while installing an app. Instead, iOS askes me to grant a permission at the time when an app actually needs to use it. This makes for a much better user experience, because it doesn't overwhelm the user with a huge list of permissions at once, and it is usually implicitly clear what the permission is for. For example, if I ask an app to scan a bar code, and the phone prompts me to grant camera permission to the app, it's really easy to understand why the app needs this permission. At install time, it might not even be clear that the app has a feature to scan bar codes.

Android Marshmallow essentially works like iOS in this regard, with the caveat that not all apps are built for Marshmallow, and thus can only have permissions revoked after installation, and with risk of causing the app to crash. Additionally, Android Marshmallow still isn't as widely adopted as the older Lollipop.


Maybe someday Amazon will fix Fire OS. In the meantime, I'm reluctant to install many apps on my Fire tablet.

Thursday, March 17, 2016

Building an IR-to-RS485 Bridge


I wanted to be able to control my Somfy ST30 RS-485 shades via my universal infrared remote, so I built a simple project using an Arduino (aka a Genuino these days, if you live outside the USA) to do this. This could easily be adapted to control any serial device, either RS-232 or RS-485.

This also acts as a sniffer for my RS-485 network, which I used to observe and reverse engineer the Somfy protocol. Please see my previous post (Somfy Wire Protocol) for my documentation of this protocol.

I started with an Arduino Mega 2560, because it has four serial ports. I'm using only two at this time, one for debugging/setup over the built-in USB port, and a second for the RS-485 connection to control my shades. I plan to control addition devices later with the extra serial ports. If you only wan to control one thing, you could probably also use an ATmega32u4-based Arduino, like the Leonardo or Micro, since those have a separate USB port from the TX/RX pins.

You could mostly implement this functionality with a Raspberry Pi, but I feel a microcontroller is really the right thing, in this case. The ATmega2560 has four serial ports versus the Pi's one, and that's a problem for me, as stated above. I also prefer the simplicity of the microcontroller. The Raspberry Pi far more complex, which is necessary for some projects, but not for this one. The Arduino loses to the Pi in cost, though. The Arduino Mega goes for $46, while the top-of-the line Pi goes for $35. If I want to add the Arduino Ethernet Shield to my project, that's another $45, while the Pi has it built in. (In fact, if I want to add ethernet, it's cheaper to connect a Pi to my Arduino!) On the other hand, if I ever wanted mass-produce my project (admittedly not likely), it might be cheaper to go with the microcontroller design. (Hmm.. you can get ATmega2560 chips in bulk for about $10 a piece, which makes it a very expensive microcontroller. Haven't found the cost of the Pi's ARM1176JZF-S.)

Parts List

I chose the MAX483 chip specifically because it is designed for improperly terminated networks. Per Somfy's directions, my network is setup in a star configuration, without any termination, so this chip seemed like the right thing. (And, indeed, it works!)

The RJ45 jack is specific to how my network is setup. I wired it up via Somfy's specifications, which matches the RJ45 jack on the back of the Somfy smart switches. You may want a different kind of connector for your project, or you may need the connector wired up differently. There's no wider standard that I'm aware of. You could even plug the wires from your RS-485 network directly into your breadboard.

Schematic



A few notes about this schematic:

The IR LED is switched via the 2N2222 transistor, so as to drive it at higher brightness than the AVR can drive directly. I'm not sure these are the optimal resistor values, but they work for me.

The IRremote library by default requires this to be connected to pin 9 on the Arduino Mega. There are several other options that can be chosen by modifying IRremoteInt.h in the library directory and recompiling. And if you are using a different Arduino, it's very important to consult this file to determine the proper pin. The library uses different pins for different AVRs!

The DE and RE pins of the MAX483 are connected together with pin 2 on the Arduino. This is possible because RE is inverted on the transceiver chip. Thus, when pin 2 is high, the transceiver is configured for sending but not receiving, and the opposite is true when pin 2 is low. This means the Arduino won't see the data it is putting on the RS-485 bus, but that's fine for my purposes.

Putting it Together

See the top of this post for what this project looks like put together on a breadboard.

I added a second RJ45 jack, which is just split off the first. This gives me a port to hook up a USB-to-RS485 adapter, which allows me to use the Somfy software on the same network as my bridge. (This is how I logged protocol data, which I used to reverse engineer the protocol.) I could have simply used an RJ45 splitter, instead. Neither of these is necessary for the finished product.

In it's final home, I power the circuit by connecting the Arduino to my DVR via a USB cable. (For setup, it's powered off of my computer's USB port.)

Software

I used Ken Shirriff's IRremote libary, which is pretty awesome! One thing to note is that newer versions of the Arduino tools contain a bastardized version of this library. (Seriously, Arduino folks, what were you thinking?) You might want to remove the "RobotIRremote" directory from your Arduino installation to make sure there's no conflict. Unlike the original IRremote, RobotIRremote has limited receiving and no sending capabilities. No good!

I've uploaded my Arduino sketch to GitHub:

https://github.com/baysinger/ir2rs485/tree/1.0

I plan to keep this git branch in sync with this blog post. The master branch may drift.

Build the sketch and upload it to the Arduino using the Arduino software suite.

Using It

Test the RS-485 Connection

With the project connected to the RS-485 network, and the USB port on the Arduino connected to a computer running the Arduino software, it's time to test things out. Open the Arduino serial monitor and set the line ending to carriage return.

Find out your motor address. If the label on the motor says the address is AB C1 23, you can convert this to network format by reversing the byte order (23 C1 AB) and then flipping every bit (DC 3E 54). I'll use DC3E54 in this example.

Try lowering the shade by issuing this command in the serial monitor:

mffffffdc3e54fdffff (substitute your motor address, in network format, for dc3e54)

Note that it is important for all letters to be lowercase. I didn't bother to write the code to process uppercase letters.

Now to raise the shade again:

mffffffdc3e54feffff

Programming the Remote

You should pick a 16-bit IR code for each command you wish to issue with the remote. I wrote the code to partition the 16 bits into a high order byte to specify the motor or group, and a low order byte to specify the command. So, for instance, I have these motors and groups (in hexadecimal):

10: All shades
20: Most shades (a group the contains all but one of my shades)
30: All the dining room shades
01: Sliding door
02: Dining room left
03: Dining room middle
04: Dining room right
05: Living room
06: Stairs

And these commands:

01: Up
02: Down
04: Stop

So, for example, the IR command for all shades up is 1001. The command for living room down is 0502.

To program the remote, you need to tell the Arduino to send an IR signal, and then you can have the remote learn that signal. To tell the Arduino to send the IR code for all shades up, enter this command into the serial monitor:
i1001
You'll also need to modify the Arduino sketch to recognize these codes when the remote sends them. (You can do this before or after programming the remote.) Open the sketch and find this switch statement:
switch (results.value >> 8) {
This section maps the high order byte received via IR to a motor or group address. You'll need to modify the case labels below that. For instance, this case label maps the value 10 to the group address 323456:
case 0x10:
   Serial.print("all ");
   uGrp = 0x323456;
   break;
And this one maps the value 01 to the motor address DBF6F9:
case 0x1:
   Serial.print("sliding door ");
   uAddr = 0xDBF6F9;
   break;
Modify this switch statement to match your setup.

Done!

Now, as long as everything is connected, you should be able to control the shades with the remote control!

Tuesday, March 1, 2016

Somfy Wire (RS-485) Protocol

Somfy uses a very simple protocol for controlling the motors over RS-485, and it has been fairly easy to reverse engineer, so far. Somfy even provides the "ILT Command Calculator" utility (available at https://www.somfypro.com/downloads), which will show the raw bytes of every control command for a given motor or group address. I have provided information on all the control commands that are covered by Somfy's command calculator. There are also a number of other messages, and I have decoded a couple of those, too.

Overall Message Format

All messages that I've decoded so far follow the same basic format:

  • Byte 0: Message ID
  • Byte 1: Message length, subtracted from 0xFF
  • Byte 2: Unknown
  • Bytes 3..N: Payload
  • Bytes N..N+1: Checksum

Length

The length is the overall length of the message, including the ID, length field, payload, and checksum. It is encoded by subtractin from 0xFF. For example, a length of 14 bytes would be encoded as F1.

Checksum

The checksum bytes simply contains the lower two bytes of the summation of all the previous bytes of the message, in big-endian order.

Control Commands

The control command message used a message ID of 0xAB. The entire message contains these fields:
  • Byte 0: Message ID (AB)
  • Byte 1: Message length (F1, decoded to 14)
  • Byte 2: Unknown (observed to be FF)
  • Bytes 3..5: Group address
  • Bytes 6..8: Motor address
  • Byte 9: Command
  • Bytes 10..11: Parameters
  • Bytes 12..13: Checksum

 

Addresses

The command either addresses a motor or a group, but not both at once. The unused address field is set to FF FF FF.

The motor address is the real address of the motor, not the ST30 address that is printed on the motor label (assuming it's an ST30 motor). I can't figure out why Somfy just doesn't print the real address on the motor label! Anyway, the conversion formula is very simple: reverse the order of the bytes and flip every bit. So, for instance:

Label Address: 06091F (00000110 00001001 00011111‬)
Real Address: E0F6F9 (11100000 11110110 11111001‬)

 

Command Byte

The command byte is one of the following:
  • FE: Up
  • FD: Down
  • FC: Stop
  • FA: Next IP UP
  • F9: Next IP DOWN
  • FB: Go to IP
  • EF: Go to %
  • F5: Jog Up 10 ms
  • F4: Jog Down 10 ms
IPs are preset positions which are configured into the motor via the configuration utility at the above link. There are also some lock commands visible in the calculator tool, but I haven't documented them, because I haven't really looked into what they do.

Parameters

The parameter bytes are only used for some commands. For commands that don't take parameters,  these bytes should be FF. If a parameter byte is used, it's encoded by subtracting from FF. So 10 is encoded as F5. Of the above commands, the following take one parameter in the first parameter byte (values shown without encoding):

  • Down: 0 or 10-255 (I'm not sure what this parameter is used for. The default seems to be 0, encoded as FF.)
  • Go to IP: IP index (1-16)
  • Go to %: Position (0-255)
  • Jog Up/Down 10 ms: 1-255 (I'm not sure what this is used for. Number of 10 ms increments?)

 


Examples

Here are some examples of complete commands:
Tell motor with address ABCDEF to go up: AB F1 FF FF FF FF AB CD EF FE FF FF 0A FB
Tell group with address FEDCBA to go up: AB F1 FF FE DC BA FF FF FF FE FF FF 0B 28
Tell motor with address ABCDEF to go to 50%: AB F1 FF FF FF FF AB CD EF EF 80 FF 0A 6D

 

Other Messages


There are a number of other messages that are not shown in the ILT Command Calculator. These are are used for things like configuration (setting limits, group addresses, preset positions, etc.) as well as querying information from the motors (position, configuration). These are used by the "ILT2-ST30 Configuration Tool" (see Somfy link above). I was interested in being able to query the positions of my shades, so I decoded those messages. I haven't looked into any other messages.

Position Query

To query the position of the motor, the tool sends a message like this:
BB F4 FF 80 80 80 E0 F6 F9 6 FD
This contains the following fields:
  • Byte 0: Message ID (BB)
  • Byte 1: Message length (F1, decodes to 14)
  • Byte 2: Unknown (observed to be FF)
  • Bytes 3..5: Group address
  • Bytes 6..8: Motor address
  • Bytes 9..10: Checksum
The fields are used just like in the command messages above, except I've noticed the tool sets the group address to 80 80 80 instead of FF FF FF. In my experimentation, it doesn't seem to matter as long as a motor address is supplied.

You can send a position query to a group of motors by setting the motor address field to FF FF FF while setting the group address appropriately, and all the motors in that group will reply. I'm not sure this is a good idea, because the motors might try to talk over each other, but in practice, I haven't had this be an issue.

Position Reply

The motor replies with a message like this:
9B F1 DF E0 F6 F9 80 80 80 38 FB 60 08 4D
This contains the following fields:
  • Byte 0: Message ID (9B)
  • Byte 1: Message length (F1)
  • Byte 2: Unknown (observed to be DF)
  • Bytes 3..5: Motor address
  • Bytes 6..8: Group address, always the same as in the query message
  • Bytes 9..10: Position in pulses from top (encoded)
  • Byte 11: Relative position (0 is bottom limit, FF is top limit)
  • Bytes 12..13: Checksum
The position in pulses is encoded in little-endian, unlike the checksum (go figure!) and subtracted from 0xFFFF (as Somfy seems to like to do).

Sunday, April 10, 2011

Connecting the motor via RS-485

I used the USB to RS-485 Converter from SparkFun (BOB-09822) ($19.95) and the cable included with the motor to connect the motor to the USB port on my computer.


Note that the converter does not come with the screw terminals shown in the picture. That's sold separately by SparkFun (for $1.50) and you have to solder to the board yourself. The board also has holes to solder in an RJ-45 connector, but beware, the pinout is different than what Somfy uses for RJ-45 on their products. The USB cable is also not included.

Next, I installed the software, which is a free download from http://somfy.us/SDNConfig.htmlhttps://www.somfypro.com/downloads. Look for ILT2-ST30. (Thanks go to Moggie on AVS Forum for pointing me to the link, which I wouldn't have found, otherwise.) I should say, I tried to install the software, because it failed the first time with some file permission error. I tried running the installer as administrator, which got further, but failed on another file permission later in the process.

What finally worked was installing the software in a virtual machine running Windows XP. (I'm running Windows 7. Presumably you wouldn't have to go through all of this if you were running Windows XP to begin with.) I used Window XP Mode, which is a free download from Microsoft available for certain versions of Windows 7.

Update (March 4, 2016): The latest version of this software seems to work fine on Windows 10 with no need for a virtual machine.

Here's what the software looks like, once it's finally up and running:


If you just have one motor connected to the network, you can click the "Get Motor Address" button to find out the address. Once you've got the address, you can check the "ST30" checkbox, and it will display the same address as is printed on the motor. (Don't ask me why this extra step is necessary.) The motor also comes with stickers with the addresses printed on them, so you can stick these on a diagram or something, which is probably useful for large installations. It's not possible to read the address that's printed on the motor without disassembling the shade.

With the address inputed, you can use the "Get All Motor Data" button to read and display all of the motor's current settings.

You can use this software to set intermediate positions, motor speed, a textual label, and group addresses (more on groups in the next post), as well as adjust the limits, and do some other stuff that I don't understand. You can also send a bunch of command, like:

  • Go to the up or down limit
  • Go to one of the 16 stored intermediate positions
  • Go to a certain number of pulses from the top (There are more than 100 pulses per revolution of the motor, so this gives you very precise control of the shade position.)
  • Go to a percentage (whole number between 0-100) between the up limit and down limit
Somfy doesn't seem to publish their protocol, but they do publish an app called "ILT Command Calc" (available from the same link at the motor config software), which will show you the commands that need to be sent over the wire to do the things listed above. It doesn't look like it would be difficult to reverse engineer the protocol.

I programmed the motor with a label, "Dining Room Left", and made it a member of two groups, for which I made up the IDs 123456 and 654321. More about this when I a talk about the smart switches, next time.

Sunday, April 3, 2011

Mounting the shade and trying it out

The fascia brackets are the same depth as the frame (3 inches), and the mounting holes are really close to the corners. This meant I couldn't put screws in the holes at the front of the frame, because those would just go into drywall.

I think it would have been secure enough with just the screws at the back, but there was another problem. The tab that you see sticking out in the picture above goes into a slot at the end of the motor. But if it's not close enough to parallel with the axis of the motor, it doesn't slide in all the way. The frame is actually wider at the back than the front, so I shimmed behind the bracket with some folded up paper. To get the front to sit against the frame, I drilled two holes in the bracket where I could put screws into the wood.

I also bent the tab down slightly with pliers to get it lined up properly.

So here's the shade installed:


And in the down position:


And here it is in action:



I will say, I was somewhat disappointed in the noise this makes. It's not that loud, but I wouldn't call it "silent" or "ultra quiet" or say that it could be "barely heard" from three feet away. It's not too bad, I guess, but it's definitely louder than I was expecting.

Using the limit setting tool was fairly easy. Instructions were included with the motor. Note that the limit setting tool just closes the contacts on the motor's dry contact port. There are four pins on the connector: up, stop, down, and ground. So you could easily make your own limit setting tool, if you really wanted.

Next time: interfacing with the computer.

First shade has arrived

My first roller shade arrived, along with accessories:

Pictured above:

  • Fascia and brackets
  • Shade
  • Internal hem bar (removed from shade)
  • Somfy Sonesse 30 (ST30) RS-485 motor (Somfy #1000658)
  • Power and RS-485 cables (included with motor)
  • End plug
  • Limit Setting Tool (Somfy #9014599)
  • Meanwell DRP-240-24 power supply
  • Power/Control Distribution Board (Somfy #1870193)
  • Smart Switches (Somfy #1810827 and #1810828)
Everything above was purchased from AV Outlet, except for the power supply, which I got off of Ebay.

I decided to just purchase one shade first, so I could make sure that this was really what I wanted.

The roller tube came with a bunch of metal shavings in it:

I cleaned this out, since I don't want any of this getting into the motor.

One thing missing here is the cable for the dry contact port on the motor, which is also used to connect the limit setting tool. It seems like this should have been included with the motor, so I fired off and email to AV Outlet. (Update: I just received the cable from AV Outlet. They were great about this.) In the meantime, I figured out a workaround. The RS-485 cable has a three conductor connector, which will fit in the four connector dry contact port:


The ground pin in the port is the same ground as the power port, so I plugged in the three pin connector such that it didn't cover the ground. I then used an alligator clip to jump the ground from the power supply output to the ground on the limit setting tool. Here's what my temporary wiring looks like:



Note there's a fuse (2 amps) in between the power supply positive terminal and the power lead for the motor. The power/control distribution panel has it's own fuses, which is what I will use in the final setup.

Next post will about mounting the shade.

Friday, April 1, 2011

First Post!

Welcome to my humble blog! I hope to use this blog to document my home automation system, as I build it. I don't know if anyone will find this interesting, but I'd like to document it for myself, if nothing else.