EDIMAX Smart Plug SP-1101W – Simple Python API

I puzzled the findings from my previous posts regarding the EDIMAX Smart plug (Basics, Scheduling) together and uploaded a simple Python API for the plug to my github. More details are available in the README of the project.

EDIMAX SP-W1101W

EDIMAX SP-W1101W

To give a quick impression of the API, here some examples (full code is here):

Set/Get plug state

# import plug API
from ediplug.smartplug import SmartPlug

# create plug object for plug with IP 172.16.100.75, login admin and password 1234
p = SmartPlug("172.16.100.75", ('admin', '1234'))

# change state of plug to ON
p.state = "ON"
print("Plug is now: ", p.state)

# change state of plug to OFF
p.state = "OFF"
print("Plug is now: ", p.state)

Set/Get scheduling

# import plug API
from ediplug.smartplug import SmartPlug

# create plug object for plug with IP 172.16.100.75, login admin and password 1234
p = SmartPlug("172.16.100.75", ('admin', '1234'))

# write schedule for one day to plug (Saturday, 11:15 - 11:45)
p.schedule = {'state': u'ON', 'sched': [[[11, 15], [11, 45]]], 'day': 6}

# query and print current schedule
print(p.schedule.__str__())

# write schedule for one week
p.schedule = [
        {'state': u'ON', 'sched': [[[1, 0], [1, 30]]], 'day': 0},
        {'state': u'ON', 'sched': [[[2, 0], [2, 30]]], 'day': 1},
        {'state': u'ON', 'sched': [[[3, 0], [3, 30]]], 'day': 2},
        {'state': u'ON', 'sched': [[[4, 0], [4, 30]]], 'day': 3},
        {'state': u'ON', 'sched': [[[5, 0], [5, 30]]], 'day': 4},
        {'state': u'ON', 'sched': [[[6, 0], [6, 30]]], 'day': 5},
        {'state': u'ON', 'sched': [[[7, 0], [7, 30]]], 'day': 6},
    ]

# query and print current schedule
print(p.schedule.__str__())

EDIMAX Smart Plug Switch SP-1101W – Scheduling

As an response to my article on operating the EDIMAX Smart Plug with Python today I got an E-Mail from Jorge, asking if I could give some details on how to program the schedule of the EDIMAX Smart Plug. So here are some basics on how this could be done through HTTP/XML (sorry, no Python code yet basic Python API supporting scheduling).

01_http_post.sh

This is the shell script I use to post the example XML requests and print the results from the plug.

02_getsched.xml

Sample XML to query the current scheduling set on the plug. E.g. the following call:

./http_post.sh getsched.xml

Would return a result as shown in 02_getsched_response.xml. For each day we have an entry like:

 <Device.System.Power.Schedule.X value="ON">...</Device.System.Power.Schedule.X>

X = 0 is Sunday, X = 1 is Monday, X = 6 is Saturday. The “value” attribute is “ON” if the schedule for this day is active or “OFF” if disabled. The data of the “Device.System.Power.Schedule.X” tag is 360 bytes long. Each hour is represented by 15 bytes, thus 360 bytes = 24h.

Each byte in the hour could represent 1, 2, 3 or 4 minutes on an ending interval:

0 = 0 min
8 = 1 min
C = 2 min
D = 3 min
F = 4 min

And on an beginning interval:

0 = 0 min
7 = 1 min
3 = 2 min
1 = 3 min
F = 4 min

The sum of all hour bytes is 60. Thus, a full hour of scheduling could be represented by:

FFFFFFFFFFFFFFF

Half an hour would be:

FFFFFFFC0000000

This is because F = 4 min., C = 2 min. and thus: 4 + 4 + 4 + 4 + 4 + 4 + 4 + 2 = 30 min.

04_sched_sun_0100-0130.xml

So for example set a schedule for Sunday from 01:00 till 01:30, we could send the XML as shown in “04_sched_sun_0100-0130.xml”.

Propeller Tool-Chain Installer (GCC, SPIN, BST, ..) Updated

I updated my installer-script for the Parallax Propeller tool-chain (GCC, SPIN, BST and others) to make it work (agin) on Ubuntu 14.04. Main issue was that the current “makeinfo” seems not to be happy with some of the “.texi” files from “binutils” used by the Propeller GCC. Thus, I added a patch to the script to solve this problem. Also the open-source-spin compiler needed a small patch since it now uses “stricmp” which is not POSIX and thus not known …

Finally I dropped support for the “loader” hack which allowed compilation of the “propgcc” on non Intel platforms. This is not any more such an issue since cross-compiling of “propgcc” is now supported (see “propgcc” README).

NOTE: if you are on a 64bit platform an you are going to install BST Tools, you need to make sure to install the required i386 libraries since BST binaries are 32bit only. On Ubuntu 14.04 the following should do the trick:

sudo apt-get install libgtk2.0-0:i386

Operate Real Light From ComputerCraft

Recently I got notice about ComputerCraft, a Minecraft mod which is all about computers and programming in Minecraft. Each computer block could be connected to redstone in-/outputs, and is programmable in Lua. Today I installed the mod and played a little with it. The result is: I am now able to use a redstone switch to turn on/off a real life light. As a back end I use my recent work on RCSwitch, running on the Pi (using the Python REST-Server to accept command), and making a HTTP-post request from ComputerCraft/Lua. Pretty simple, pretty impressive.

Hacking an SD-Card to Micro Python on STM32F4-Discovery

Some time ago, I wrote about how to install the amazin Micro Python on the STM32F4-Discovery. While this works very well, one might easily come to the point where the internal flash memory of the STM32 will be not enough. I guess, this is why the Micro Python board comes with an micro SD card slot. On the STM32F4 there is no such slot, and Micro Python does not enable SD card support for this board by default. But this could easily be changed by using an Micro SD to SD card adapter which could be connected to the STM32.

STM32 with SD Card

STM32 with SD Card

Btw.: Mirco Python accesses the SD Card through SDIO in 4-Bit mode which makes the access pretty fast …

Patch the Micro Python Sources

In general, build Micro Python for the STM32F4-Discovery as already described in this article. But since the original sources have no SD enabled for the STM, before compiling the following changes need to be made to the Micro Python source code:

To enable SD card support, and specify SD card detection switch, edit stmhal/boards/STM32F4DISC/mpconfigboard.h like this:

#define STM32F4DISC

#define MICROPY_HW_BOARD_NAME       "F4DISC"
#define MICROPY_HW_MCU_NAME         "STM32F407"

#define MICROPY_HW_HAS_SWITCH       (1)
#define MICROPY_HW_HAS_SDCARD       (1)
#define MICROPY_HW_HAS_MMA7660      (0)
#define MICROPY_HW_HAS_LIS3DSH      (1)
#define MICROPY_HW_HAS_LCD          (0)
#define MICROPY_HW_ENABLE_RNG       (1)
#define MICROPY_HW_ENABLE_RTC       (1)
#define MICROPY_HW_ENABLE_TIMER     (1)
#define MICROPY_HW_ENABLE_SERVO     (0)
#define MICROPY_HW_ENABLE_DAC       (0)
#define MICROPY_HW_ENABLE_I2C1      (1)
#define MICROPY_HW_ENABLE_SPI1      (1)
#define MICROPY_HW_ENABLE_SPI3      (0)
#define MICROPY_HW_ENABLE_CC3K      (0)

// USRSW is pulled low. Pressing the button makes the input go high.
#define MICROPY_HW_USRSW_PIN        (pin_A0)
#define MICROPY_HW_USRSW_PULL       (GPIO_NOPULL)
#define MICROPY_HW_USRSW_EXTI_MODE  (GPIO_MODE_IT_RISING)
#define MICROPY_HW_USRSW_PRESSED    (1)

// LEDs
#define MICROPY_HW_LED1             (pin_D14) // red
#define MICROPY_HW_LED2             (pin_D12) // green
#define MICROPY_HW_LED3             (pin_D13) // orange
#define MICROPY_HW_LED4             (pin_D15) // blue
#define MICROPY_HW_LED_OTYPE        (GPIO_MODE_OUTPUT_PP)
#define MICROPY_HW_LED_ON(pin)      (pin->gpio->BSRRL = pin->pin_mask)
#define MICROPY_HW_LED_OFF(pin)     (pin->gpio->BSRRH = pin->pin_mask)

// SD card detect switch
#define MICROPY_HW_SDCARD_DETECT_PIN        (pin_A8)
#define MICROPY_HW_SDCARD_DETECT_PULL       (GPIO_PULLUP)
#define MICROPY_HW_SDCARD_DETECT_PRESENT    (GPIO_PIN_RESET)

Wiring the SD-Card to the STM32F4-Discovery

The SD card and the STM need to be wired as follows:

SD-Card       STM32F4-Discovery
-------------------------------
1 SDIO_D3     PC11
2 SDIO_CMD    PD2
3 VSS         GND
4 VDD         3V
5 SDIO_CLK    PC12
6 SDIO_SW     PA8
7 SDIO_D0     PC8
8 SDIO_D1     PC9
9 SDIO_D2     PC10

The pins on a SD card are numbered like this:

 ___________________
/   1 2 3 4 5 6 7 8 |
| 9                 |
|                   |

Note: PC10/PC12 are also connected to the CS43L22,but this seams not to be a problem as long as you don’t use both: SD and CS43L22. Also it is suggested to use some pull-ups (47k) on SDIO_CMD, SDIO_D0, SDIO_D1, SDIO_D2, SDIO_D3, but I decided not to care :-).

Prepare the SD Card

Not much to do here, Just make sure to format the SD card to use with FAT-FS. On Linux, this is done like so (instead of sdc1 use the partition of your SD card!!):

mkfs.fat /dev/sdc1

Use the SD Card

Now, with the new SD card attached, reset the STM32 Micro Python board. After some time, the SD card should show up on your Linux as a empty new drive (e.g. as 4.0 GB Volume). Next, let’s connect to the Python shell on the board (e.g. by “screen /dev/ttyACM0 115200″) and see if we could access the card.

Note: the Micro Python web page states, that if a SD card is present, booting will be done from this card. However, it seams that on the STM32 booting is still done from internal flash, but the SD card is accessible anyway.

First, lets write a file to the SD card. In Micro Python, the internal Flash has the paht “0:/” and the SD card has “1:/”. Knowing this, it is pretty simple to write “Hello World” into a file on the card:

f = open("1:/hello.txt", "w")
f.write("Hello World from Micro Python")
f.close()

After a reset, the new file “hello.txt” should be shown on the SD card under Linux.

Ok, this is all fine, but how about storing and loading Python modules on the SD card? From Linux, let’s put the following sample (named “blink.py”) to the SD card:

import pyb

leds = [pyb.LED(i) for i in range(1,5)]
for l in leds: 
    l.off()

n = 0
try:
   while True:
      n = (n + 1) % 4
      leds[n].toggle()
      pyb.delay(50)
finally:
    for l in leds:
        l.off()

Reset Micro Python with “Ctrl-D”, and try the following:

import blink

Which will end in an erro:

Traceback (most recent call last):
  File "", line 0, in 
ImportError: No module named 'blink'

This is because Python is only searching “0:\” and “0:\lib” for modules by default. We could easily fix this by doing the following:

import sys 
sys.path.append("1:/")
import blink

It might be a good idea to put the above into “main.py” on the internal flash …

Linux Kernel Module to Control 434Mhz RC Outlets – Pi Version

Added a setup-script to cross-compile the Linux kenel module for the RC outlets for the Raspbarry Pi. To be able to cross-compile the module, in brief the following needs to be done:

Install ARM cross-gcc

On Ubuntu:

sudo apt-get install gcc-arm-linux-gnueabi make ncurses-dev

Get RasPi Kernel

E.g. use Kernel from GIT:

git clone https://github.com/raspberrypi/linux.git linux-raspberrypi

Compile the Kernel (needs to be done once before building the rcswitch-kmod)

To be able to compile out-of-tree Kernel modules, you need to cross-compile the targets Kernel at least once. This is done like so:

cd linux-raspberrypi
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- bcmrpi_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

Depending on your machine, this may take some time …

Build rcswitch-kmod

Get the module from git:

git clone https://github.com/wendlers/rcswitch-kmod.git rcswitch-kmod
cd rcswitch-kmod

Edit setenv_raspi.sh, make sure LINUX_DIR points to the directory of your previously build kernel:

export LINUX_DIR=$PWD/../linux-raspberrypi

Next, build the module:

source ./setenv_raspi.sh
make all

Now copy the Kernel module to your PI. E.g. by using ssh:

 
scp module/src/rcswitch.ko pi@:/home/pi/.

Wiring the RF Transmitter to the PI (to use Kernel module defaults)

To use the modules build in default, connect the RF-Transmitter as shown in the picture below:

Connect transmitter to PI

Connect transmitter to PI

Loading the Module, Testing Module

On the Pi, the module could be loaded like this:

sudo su
insmod /home/pi/rcswitch.ko

Verify the module was loaded properly:

dmesg

Should output something like this:

[ 3392.757506] rcswitch: init
[ 3392.757540] rcswitch: using tx_repeat of 10
[ 3392.757609] rcswitch: registered command interface under: /sys/kernel/rcswitch/command
[ 3392.757623] rcswitch: registered power   interface under: /sys/kernel/rcswitch/power
[ 3392.757641] rcswitch: using gpio #17 for TX
[ 3392.757650] rcswitch: EN disabled

And the following sysfs entries should have bean created:

ls -al /sys/kernel/rcswitch
--w--w--w- 1 root root 4096 Jul 25 23:15 command
-rw-rw-rw- 1 root root 4096 Jul 25 23:46 power

If all of the above is in place, you should be able to operate your switches. E. g. turn on switch at address 11111, channel A:

echo 11111A1 > /sys/kernel/rcswitch/command

And to turn the same switch off:

echo 11111A0 > /sys/kernel/rcswitch/command

Note: there is also a python example which could be used on the Pi here.

Tri-State Protocol of the Pollin (and other) 434MHz RC Switches

Made a overview of how the over-air protocol looks for the Pollin RC Switches (see previous article for more details). The length of the pulses is a multible of 350us. The wave-forms where captured with an OpenBench logic sniffer.

RCSwitch Tri-State-Protocol

RCSwitch Tri-State-Protocol

Linux Kernel Module to Control 434Mhz RC Outlets

Some time ago, I wrote about using an EDIMAX Smart Plug with Python. The EDIMAX has build in Wifi and runs its own web server. While this is convenient, it also makes the EDIMAX quiet expensive. Lately I got notice (thanks Eric), about very cheap 434MHz based plugs sold by Pollin for less then 10 EURO per 3 pieces (including a remote control I will not need anyway). Also there are libraries for using them with a cheap 434MHz transmitter as well as some remote control software for the RaspbarryPi.

What I didn’t like about the existing solutions was the fact, that the driver ran in user spacing using wiringPi to access the GPIOs. To my opinion there is absolutely no need to wrap all this low-level stuff in user-space. The Linux kernel itself provides a very good abstraction layer to access GPIOs in a machine independent way. Also exposing functionality could be done easily through sysfs.

Thus, I decided to somehow rewrite the above code (rcswitch-pi) to live in a Kernel module being accessible through sysfs. The complete results could be found here.

Operating the outlets now becomes very simple and could be done from almost any programming language. Even from bash.

E.g. to turn the power on for address ‘11111’ and channel ‘A’ one could use:

echo "11111A1" > /sys/kernel/rcswitch/command

Or to turn the power off for the same device:

echo "11111A0" > /sys/kernel/rcswitch/command

I also included optional power-management, allowing the transmitter to be turned on/off (if VCC of the transmitter is connected to an GPIO):

Power on the transmitter:

echo "1" > /sys/kernel/rcswitch/power

Power off the transmitter:

echo "0" > /sys/kernel/rcswitch/power

Get current power state of the transmitter:

cat /sys/kernel/rcswitch/power

This far, I only tested the module on my 8Devices Carambola board (running kernel 3.3.8). But it should work without modifications for any other Linux board.

For more instructions, please see the projects README.

More links regarding RC outlets:

And some pictures of mine:

433MHz transmitter

434MHz transmitter

RC outlets

Pollin RC outlets

Poor Mans 3D Goggles (OpenDive)

At Google I/O this year, Cardboard was presented. Cardboard are DIY 3D goggles made of cardboard, using a smart phone as screen and sensor device. Cardboard seams to be based on OpenDive from Stefan Welker who also published the STL files for 3D printing his goggles on ThingiVerse. And printing them was exactly what I did lately.

Obviously not all parts could be printed. One needs fitting lenses and some rubber band to “mount” the goggles on the head. Stefan Welker used to offer a kit on amazon, including lenses and rubber band. Unfortunately it looks like Google bought all the Kits for Cardboard. Thus, I replaced the lenses with the 30mm 5x ones included in this set. They do not fit in the original lens holders, but they do fit with this holders available at ThingiVerse.

The rubber band is a 40mm rubber band easily available. I used this one from amazon.

The results one gets with the OpenDrive are amazingly good! Especially playing Quake 2 is real fun! The only down side is, that there are not many (real) games available yet.

Some more links regarding OpenDive:

And some pictures of my OpenDive:

OpenDive printing phone clips

OpenDive printing phone clips

OpenDive lense holders

OpenDive lense holders

OpenDive lense holders and lenses

OpenDive lense holders and lenses

OpenDive printing  frame

OpenDive printing frame

OpenDive assembled (back)

OpenDive assembled (back)

OpenDive with lenses in place (top)

OpenDive with lenses in place (top)

OpenDive with lenses in place (bottom)

OpenDive with lenses in place (bottom)

OpenDive assembled (front)

OpenDive assembled (front)

OpenDive assembled

OpenDive assembled

OpenDive assembled

OpenDive assembled

OpenDive assembled

OpenDive assembled

Bric(k)-o-lage – Big Button

I created a first passive component for my brick-o-lage project: a big button with feedback LED. The button is mode from a big “pilz” switch which presses a smaller switch inside the case. Very simple but dangerous looking :-). The 3D files could be found on my github account. I tried to make the case stable enough so it could be hit hard too.

Big Button - Inside

Big Button – Inside

Big Button - Top

Big Button – Top

Big Button - LED

Big Button – LED

Since the bricks do have whole which are LEGO Technics compatible, they could be plugged together:

Plug Together (1)

Plug Together (1)

Plug Together  (2)

Plug Together (2)

Plug Together  (3)

Plug Together (3)

Big Button Brick Specifications

  • One Pliz-Switch (40mm)
  • One small switch
  • Some wire, plug

Big Button Brick Case

Big Button

Big Button

Big Button - Exploded

Big Button – Exploded