Loxone Einbindung der Termine der Stadtreinigung Hamburg

A quick Loxone Tip for People in Hamburg, Germany. That’s why it is in German…

 

Etwas ganz spezielles für die Hamburger Loxone Miniserver Nutzer: ein PicoC Programm, welches es erlaubt mit seiner Anschrift (Straße und Hausnummer) von der Stadtreinigung Hamburg die Termine der nächsten Abholungen einzubinden. Hamburg hat teilweise recht variable Termine und die sind auch nur ein paar Monate im Voraus als Kalender zu importieren. Mit dem Programm kann man folgendes erhalten:

In wieviel Tagen wird das nächste Mal folgendes abgeholt:
– Restmüll
– Papier
– Wertstoffe
– Bio
– Laub (nur im Herbst)
– Weihnachtsbäume (ja, haben wir wirklich – Termine gibt es nur im Januar)

Zudem gibt es Tage mit mehreren Abholungen (Restmüll und Papier oder Restmüll und Wertstoffe). Deswegen erzeugt das Programm auch einen handlichen Statustext für welche Tonnen und an welchem Tag (nächster Termin) bzw. einen Text wie “In 7 Tagen: Restmüll, Papier”.

Der Sourcecode ist einfach ins Programm Bauteil zu kopieren und STRASSE, sowie HAUSNUMMER durch die korrekte Angabe zu ersetzen.

https://gist.github.com/sarnau/6bfc02ff7a8623467f75fa558f55f72b

Charge Master 2016 Serial Protocol

Charge Master 2016 Serial Protocol

The Voltcraft (Conrad) Charge Master 2016 has a completely different protocol from the CM2010 and other devices.

The USB port is still a serial port which is /dev/cu.SLAB_USBtoUART on my Mac. Every second the device sends a package with 19200 baud 8N1. I’ve written a simple python script to demonstrate reading and interpreting the data. For actual use you should add some error handling.

Only one byte in the slot header is unknown (it seems the Windows software is also not using it) and the device header has a few semi-unknown ones (the version, the temperature, etc) – only the chemical setting is actually used by the Window software.

The full source code can be found on GitHub https://github.com/sarnau/cm2016.

ELV Mobile Alerts

Mobile Alerts

This document tries to describe every detail of the Mobile Alerts sensors, which are sold by ELV in Germany, but are also available at the common suspects (Amazon, etc). Be careful buying at Amazon: certain sensors mention Mobile Alerts, but seem to be designed for the US. They are not compatible with the ELV Mobile Alerts ones!

Mobile Alerts is covering mostly climate sensors, but also contains moisture and door/window sensors plus a sound detector, which acts as a gateway for smoke sensors.

The Mobile Alerts are a version of the LaCrosse Alerts Mobile system made for the European market.

Detailed Infomation

68k Disassembler in C

Original 68k Disassembler I wrote for Hatari <https://hatari.tuxfamily.org> in 2010.

It does support all 68k CPUs, including the embedded ones, FPU and PMMU.

It doesn’t compile on it’s own, but requires Hatari source code. But it should be possible with minimal effort to make it stand-alone. All sources can be found on GitHub.

Unit Calculator in Objective C

An piece of code I wrote in 2006, which allows you to do mathematical calculations with units from Objective-C. I’ve updated the code to Objective-C with properties and generics. It is not depended on macOS and should work fine on iOS as well.

By default the result will be in SI compatible units, but all units and prefixes (like kg or ms) can be freely defined in a configuration file units.dat. You can also force a specific unit and add variables to the term. It is also trivial to add new functions, even functions which accept a list of values.

A few examples:

((123.45e-1 + sqrt(+4) -4-.69/2)*2^1/5)^2 => 16
 avg(1,2,3,4) => 2.5
 (9*m^2)^0.5 => 3 m
 60 m + 2 mm => 60.002 m
 sqrt(9 m^2) => 3 m
 20 lb requestedUnit: kg => 9.07185 kg
 60 km/h + 12 m/s requestedUnit: km/h => 103.2 km/h
 1 Torr*760 requestedUnit: atm => 1 atm
 68 F requestedUnit: C => 20 C
 0 C + 0 C requestedUnit: C => 273.15 C --- internally temperatures are converted to Kelvin

The project is an Xcode project with a simple NSLog in the app delegate for testing. It also has a bunch of unit tests to make sure the math works out in all cases.

The code can be found on GitHub.

Label Placement

Implementation of a little algorithm to draw labels/rectangles on a background while trying to avoid overlapping. This is useful for maps, drawing labels on graphs, etc. The sources are – as always – available on GitHub.

In the screenshots you can see the planned area in light grey, while the repositioned ones are in black. The size of the rectangles is arbitrary.

The implementation is specifically simple and not optimized for performance at all. The goal is to be able to understand it.

Raspbian Jessie with a Pi-Raq LCD

The Pi-Raq came with an old version of Raspbian. An upgrade to e.g. Jessie will render the display non-functioning. The manufacturer sadly never got back to me, so I fixed it myself.

Download the archive with all needed files from GitHub.

There are two main things to do:

  1. Provide a custom dt-blob.bin for the pin configuration. This has changed with later version of Raspbian and is the reason why the old file no longer works.
  2. Update a stock config.txt to switch to the LCD.

How to modify the dt-blob.dts

There is very few documenation for this, which is expected, considering that hooking up a custom LCD to a Raspberry is not a very common thing to do.

I used the stock dt-blob.dts as a new base. First I stripped it down, because the Pi-Raq ships with a “Pi 2 Model B rev 1.1” only, which means all other pin configurations are not used anyway and I can’t test it. If you try to use it with a different Raspberry Pi (which seems possible), you have to change the pins_2b2 to match your Raspberry Pi. Use the stock version as an example and transfer the changes over.

By looking at the “Pi-RAQ Hardware Schematic.pdf” you can find out all custom pin mappings:

  • Pin 0 => PCLK-Out (pixel clock)
  • Pin 1 => DE-Out (display enable)
  • Pin 4–8 => B3-B7-Out (5 bits for blue)
  • Pin 9–14 => G2-G7-Out (6 bits for blue, our eyes are more sensitive to green)
  • Pin 15–19 => R3-R7-Out (5 bits for blue)
  • Pin 20–26 are for the jog shuttle controls. They don’t need a custom config, because they are already covered by the pin@default case.
    • Pin 20 = Right button
    • Pin 21 = Left button
    • Pin 22 = Rot1
    • Pin 23 = Center button
    • Pin 24 = Rot2
    • Pin 25 = Down button
    • Pin 26 = Left button
  • Pin 27 is the output for the backlight of the LCD. It has to be an output and should have a startup_state of “active”, otherwise the display stays off after boot. It can still be turned off at any time via a script.

Normal buttons are detected on a falling edge with 100ms debounce. Rotation is doing an edge-detection (both, 10ms debounce). If Rot1 changes and the Rot1 and Rot2 bits are the same, the wheel was rotated left. If both bits have a different value, it was rotated right.

Everything beyond pin 28 is not modified.

How to modify the config.txt

The config.txt has to be modified to switch from HDMI to the LCD. Besides basic changes, like turning overscan off (the LCD doesn’t have a overscan area) and set the framebuffer size to 1024×100 pixel, it is also necessary to enable dpi support (via enable_dpi_lcd), switch the default over and reconfigure the timing and output format for the dpi. Check the comments for a bit more details. The timings and the output format are specific to the LCD panel, which is connected.

Installation Step-by-Step

  1. Install Raspbian on an SD Card
  2. Use ApplePi-Baker to install Raspbian Jessie Lite (the normal version is not needed for this tiny display)
  3. Boot Raspberry with this card. You need to have a HDMI display connected and a USB keyboard
  4. sudo raspi-config => fix the keyboard layout, set a password, changed the hostname, reboot
  5. Remove the card and copy the content of this folder into /home/pi
  6. Put the card back into the Raspberry and boot the Pi-Raq again.
  7. It is typically faster to SSH into the Pi-Raq to configure it, but not necessary.
  8. Now finish the installation:

sudo nano /boot/config.txt

Uncomment/Modify the following lines, which should already be in the config.txt

disable_overscan=1

framebuffer_width=1024
framebuffer_height=100

and add this to the bottom of the file:

#----------------------------------------------------------------------------------------------------
#Generated on Thu Feb 19 13:20:39 2015 by Segler-HP
#config file for None
#Output Format -> DPI_OUTPUT_FORMAT_16BIT_565_CFG1
#RGB Order -> DPI_RGB_ORDER_RGB
#Output Enable Mode ->DPI_OUTPUT_ENABLE_MODE_DATA_VALID
#Invert Pixel Clock ->RGB Data changes on falling edge and is stable at rising edge
#Hsync Disable ->False
#Vsync Disable ->False
#Output Enable ->False
#Hsync Polarity ->Inverted
#Vsync Polarity ->Inverted
#Output Enable Polarity ->default for HDMI mode
#Hsync Phase ->DPI_PHASE_POSEDGE
#Vsync Phase ->DPI_PHASE_NEGEDGE
#Output Enable Phase ->DPI_PHASE_NEGEDGE
#----------------------------------------------------------------------------------------------------
hdmi_timings=1024 0 50 100 50  100 0 2 10 2 0 0 0  60 0 25000000 7
enable_dpi_lcd=1
display_default_lcd=1
dpi_output_format=4194306 #6488594
dpi_group=2
dpi_mode=87

The pin configuration of the device tree can be compiled from source:

sudo dtc -I dts -O dtb -o /boot/dt-blob.bin dt-blob.dts

As an alternative to you copy the dt-blob.bin

sudo cp dt-blob.bin /boot/dt-blob.bin

The Raspberry icons occupy a large amount of the vertical space during boot. They can be disabled by adding an option to the cmdline.txt:

sudo nano /boot/cmdline.txt

Add logo.nologo to the parameters. It should look like this after it:

dwc_otg.lpm_enable=0 logo.nologo console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

We should also upgrade and update our installation:

sudo apt-get upgrade && sudo apt-get update

Now we can reboot:

sudo reboot

The HDMI should now be off (and can it be disconnected) and the LCD is used

Launching the demos

To get the demos to work, we need to install a few more python specific pieces:

For AlarmTest we need pygame:

sudo apt-get install python-pygame

This demo can be launched by cd AlarmTest and then python main.py

We need pip to install more Python packages

sudo apt-get install build-essential python-dev python-pip

This is only used for rotTest:

sudo pip install psutil

This demo can be launched by cd rotTest and then python main.py. The demo can be quit via Control-C, but the display stays blank. I haven’t fixed this. sudo reboot solves it…

The full dt-blob.dts for EarthLCD Pi-Raq

/dts-v1/;

/ {
   videocore {
      clock_routing {
        vco@PLLD { freq = <2000000000>; };
        chan@DPER { div = <8>; }; // APER will be 500MHz
      }; // clock routing

      pins_2b2 { // Pi 2 Model B rev 1.1
         pin_config {
            pin@default {
               polarity = "active_high";
               termination = "pull_down";
               startup_state = "inactive";
               function = "input";
            }; // pin

            pin@p0  { function = "dpi";    termination = "no_pulling"; drive_strength_mA = < 8 >; };    // PCLK-OUT
            pin@p1  { function = "dpi";    termination = "no_pulling"; drive_strength_mA = < 8 >; };    // DE-OUT

            pin@p2  { function = "i2c1";   termination = "pull_up";    }; // I2C 1 SDA
            pin@p3  { function = "i2c1";   termination = "pull_up";    }; // I2C 1 SCL

            pin@p4  { function = "dpi";    termination = "no_pulling"; };   // B3-Out
            pin@p5  { function = "dpi";    termination = "no_pulling"; };   // B4-Out
            pin@p6  { function = "dpi";    termination = "no_pulling"; };   // B5-Out
            pin@p7  { function = "dpi";    termination = "no_pulling"; };   // B6-Out
            pin@p8  { function = "dpi";    termination = "no_pulling"; };   // B7-Out

            pin@p9  { function = "dpi";    termination = "no_pulling"; };   // G2-Out
            pin@p10 { function = "dpi";    termination = "no_pulling"; };   // G3-Out
            pin@p11 { function = "dpi";    termination = "no_pulling"; };   // G4-Out
            pin@p12 { function = "dpi";    termination = "no_pulling"; };   // G5-Out
            pin@p13 { function = "dpi";    termination = "no_pulling"; };   // G6-Out
            pin@p14 { function = "dpi";    termination = "no_pulling"; };   // G7-Out

            pin@p15 { function = "dpi";    termination = "no_pulling"; };   // R3-Out
            pin@p16 { function = "dpi";    termination = "no_pulling"; };   // R4-Out
            pin@p17 { function = "dpi";    termination = "no_pulling"; };   // R5-Out
            pin@p18 { function = "dpi";    termination = "no_pulling"; };   // R6-Out
            pin@p19 { function = "dpi";    termination = "no_pulling"; };   // R7-Out

            // Pin 20..26 are the Jog Shuttle controls, they are all inputs, which is covered by the pin@default case
            // p20 = Right button
            // p21 = Left button
            // p22 = Rot1           (Rot1 ^ Rot2) != 0 => Right, (Rot1 ^ Rot2) == 0 => Left if an edge was detected
            // p23 = Center button
            // p24 = Rot2
            // p25 = Down button
            // p26 = Left button

            pin@p27 { function = "output"; termination = "pull_up"; startup_state = "active"; };    // LCD Backlight enable, active at boot

            // From here on it is identical to Jessie's defaults:

            // The firmware changes I2C pin functions on the fly, returning them to inputs when done. But pins 28&29 are
            // not used on a 1.1 Pi2, so the I2C0 function ends up multiply mapped (bad). therefore don't statically map.
            // pin@p28 { function = "i2c0";   termination = "pull_up";    }; // I2C 0 SDA
            // pin@p29 { function = "i2c0";   termination = "pull_up";    }; // I2C 0 SCL
            pin@p31 { function = "output"; termination = "pull_down"; }; // LAN_RUN
            pin@p32 { function = "output"; termination = "pull_down"; }; // Camera LED
            pin@p35 { function = "input";  termination = "no_pulling"; polarity = "active_low"; }; // Power low
            pin@p38 { function = "output"; termination = "no_pulling";    }; // USB current limit (0=600mA, 1=1200mA)
            pin@p40 { function = "pwm";    termination = "no_pulling"; drive_strength_mA = < 16 >; }; // Right audio
            pin@p41 { function = "output"; termination = "no_pulling";    }; // Camera shutdown
            // Communicate with the SMPS by "bit-bashing" the I2C protocol on GPIOs 42 and 43
            pin@p42 { function = "output"; termination = "pull_up";    }; // SMPS_SCL
            pin@p43 { function = "input";  termination = "no_pulling";    }; // SMPS_SDA
            pin@p44 { function = "gp_clk"; termination = "pull_down"; }; // ETH_CLK - Ethernet 25MHz output
            pin@p45 { function = "pwm";    termination = "no_pulling"; drive_strength_mA = < 16 >; }; // Left audio

            pin@p46 { function = "input";  termination = "no_pulling"; polarity = "active_low"; }; // HDMI hotplug detect (goes to pin 6 of IC1)
            pin@p47 { function = "output"; termination = "pull_down"; }; // activity LED
            pin@p48 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD CLK
            pin@p49 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD CMD
            pin@p50 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D0
            pin@p51 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D1
            pin@p52 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D2
            pin@p53 { function = "sdcard"; termination = "pull_up";    drive_strength_mA = < 8 >; }; // SD D3
         }; // pin_config

         pin_defines {
            pin_define@HDMI_CONTROL_ATTACHED { type = "internal"; number = <46>; };

            pin_define@NUM_CAMERAS { type = "internal"; number = <1>; };
            pin_define@CAMERA_0_I2C_PORT { type = "internal"; number = <0>; };
            pin_define@CAMERA_0_SDA_PIN { type = "internal"; number = <28>; };
            pin_define@CAMERA_0_SCL_PIN { type = "internal"; number = <29>; };
            pin_define@CAMERA_0_SHUTDOWN { type = "internal"; number = <41>; };
            pin_define@CAMERA_0_UNICAM_PORT { type = "internal"; number = <1>; };
            pin_define@CAMERA_0_LED { type = "internal"; number = <32>; };

            pin_define@FLASH_0_ENABLE { type = "absent"; };
            pin_define@FLASH_0_INDICATOR { type = "absent"; };
            pin_define@FLASH_1_ENABLE { type = "absent"; };
            pin_define@FLASH_1_INDICATOR { type = "absent"; };

            pin_define@POWER_LOW { type = "internal"; number = <35>; };
            pin_define@LEDS_DISK_ACTIVITY { type = "internal"; number = <47>; };
            pin_define@LAN_RUN { type = "internal"; number = <31>; };
            pin_define@SMPS_SDA { type = "internal"; number = <43>; };
            pin_define@SMPS_SCL { type = "internal"; number = <42>; };
            pin_define@ETH_CLK { type = "internal"; number = <44>; };
            pin_define@USB_LIMIT_1A2 { type = "internal"; number = <38>; };
            pin_define@SIO_1V8_SEL { type = "absent"; };
            pin_define@PWML { type = "internal"; number = <45>; };
            pin_define@PWMR { type = "internal"; number = <40>; };
            pin_define@SAFE_MODE { type = "internal"; number = <3>; };
            pin_define@SD_CARD_DETECT { type = "absent"; };
            pin_define@ID_SDA { type = "internal"; number = <0>; };
            pin_define@ID_SCL { type = "internal"; number = <1>; };
            pin_define@DISPLAY_I2C_PORT { type = "internal"; number = <0>; };
            pin_define@DISPLAY_SDA { type = "internal"; number = <28>; };
            pin_define@DISPLAY_SCL { type = "internal"; number = <29>; };
         }; // pin_defines
      }; // pins

   };
};

The full config.txt

# For more options and information see
# http://www.raspberrypi.org/documentation/configuration/config-txt.md
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
disable_overscan=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

# uncomment to force a console size. By default it will be display's size minus
# overscan.
framebuffer_width=1024
framebuffer_height=100

# uncomment if hdmi display is not detected and composite is being output
#hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on

# Uncomment this to enable the lirc-rpi module
#dtoverlay=lirc-rpi

# Additional overlays and parameters are documented /boot/overlays/README

#----------------------------------------------------------------------------------------------------
#Generated on Thu Feb 19 13:20:39 2015 by Segler-HP
#config file for None
#Output Format -> DPI_OUTPUT_FORMAT_16BIT_565_CFG1
#RGB Order -> DPI_RGB_ORDER_RGB
#Output Enable Mode ->DPI_OUTPUT_ENABLE_MODE_DATA_VALID
#Invert Pixel Clock ->RGB Data changes on falling edge and is stable at rising edge
#Hsync Disable ->False
#Vsync Disable ->False
#Output Enable ->False
#Hsync Polarity ->Inverted
#Vsync Polarity ->Inverted
#Output Enable Polarity ->default for HDMI mode
#Hsync Phase ->DPI_PHASE_POSEDGE
#Vsync Phase ->DPI_PHASE_NEGEDGE
#Output Enable Phase ->DPI_PHASE_NEGEDGE
#----------------------------------------------------------------------------------------------------
hdmi_timings=1024 0 50 100 50  100 0 2 10 2 0 0 0  60 0 25000000 7
enable_dpi_lcd=1
display_default_lcd=1
dpi_output_format=4194306 #6488594
dpi_group=2
dpi_mode=87

Mobile Alerts Sensors

ELV is selling affordable weather sensors http://www.elv.de/ip-wettersensoren-system.html, which can be monitored via an iOS application. To allow that all data is transmitted via a gateway to a server, which the application can access. Sadly the protocol is not documented. I don’t think anybody has documented the way the URL has been constructed, especially the MD5 hash over the first part of it.

This sample code integrates sensors into fhem and I wrote it for Mac OS X, but it should work on Linux, too.

All information (and more) is available on GitHub as well.

To integrate the sensors into fhem, add the sensors to the iOS application and check if they show up. You need to note all sensor IDs. The ID is 6 bytes long and represented as a hexadecimal number. This same code supports sensors of type 2 (temperature only) and type 3 (temperature and humidity), which can be recognized via the first two characters of the ID.

You have to adjust the following things in the code:

  • sensors = … Here you have to add all sensors IDs as strings
  • downloadPath This needs to be adjusted to point to the log folder of fhem.
  • vendorid You might want to change the UUID to a new one (just run uuidgen from the terminal)

Python Code

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import json
import pprint
import datetime
import hashlib
import time

downloadPath = os.path.expanduser('~/fhem-5.7/log')
pp = pprint.PrettyPrinter()

sensors =  set(['021122334455',...,'031122334455'])

def parseJSON(jj):
    if not jj['success']:
        print '#%d %s' % (jj['errorcode'],jj['errormessage'])
        return
    for device in jj['result']['devices']:
        #pp.pprint(device)
        deviceTypeId = device['devicetypeid']
        deviceName = device['name']
        print '%s %s [%d] #%d %s' % (device['deviceid'], deviceName, device['lowbattery'],len(device['measurements']),datetime.datetime.fromtimestamp(device['lastseen']).strftime('%Y-%m-%d %H:%M:%S'))
        year = -1
        month = -1
        logPath = ''
        for measurement in device['measurements']:
            idx = measurement['idx']
            transmitTime = datetime.datetime.fromtimestamp(measurement['c'])
            measurementTime = datetime.datetime.fromtimestamp(measurement['ts'])
            tx = measurement['tx']
            mm = measurement
            del mm['idx']
            del mm['c']
            del mm['ts']
            del mm['tx']

            if year != measurementTime.year or month != measurementTime.month:
                if len(logPath):
                    f = open(logPath, "w")
                    for d in sorted(data):
                        f.write('%s %s\n' % (d,data[d]))
                year = measurementTime.year
                month = measurementTime.month
                logPath = downloadPath + '/S_SENSOR_%s-%d-%02d.log' % (deviceName.upper().replace(' ','_'),year,month)
                data = {}
                try:
                    for line in open(logPath).readlines():
                        vals = line[:-1].split(' ')
                        data[' '.join(vals[:-1])] = vals[-1]
                except:
                    pass
            dataKey = measurementTime.strftime('%Y-%m-%d_%H:%M:%S') + ' SENSOR_' + deviceName.upper().replace(' ','_') + ' '
            if deviceTypeId == 2:
                data[dataKey + 'TEMP:'] = '%.1f' % (measurement['t1'])
            elif deviceTypeId == 3:
                data[dataKey + 'TEMP:'] = '%.1f' % (measurement['t1'])
                data[dataKey + 'FEUCHTIGKEIT:'] = '%.1f' % (measurement['h'])
            else:
                pp.pprint(mm)
        if len(logPath):
            f = open(logPath, "w")
            for d in sorted(data):
                f.write('%s %s\n' % (d,data[d]))


import urllib
import urllib2

devicetoken = 'empty'               # defaults to "empty"
vendorid = '1FB220C4-CC15-4195-97CF-8BE4FD3DAE72'   # iOS vendor UUID (returned by iOS, any UUID will do). Launch uuidgen from the terminal to generate a fresh one.
phoneid = 'Unknown'                 # Phone ID - probably generated by the server based on the vendorid (this string can be "Unknown" and it still works)
version = '1.21'                    # Info.plist CFBundleShortVersionString
build = '248'                       # Info.plist CFBundleVersion
executable = 'Mobile Alerts'        # Info.plist CFBundleExecutable
bundle = 'de.synertronixx.remotemonitor'    # [[NSBundle mainBundle] bundleIdentifier]
lang = 'en'                         # preferred language

request = "devicetoken=%s&vendorid=%s&phoneid=%s&version=%s&build=%s&executable=%s&bundle=%s&lang=%s" % (devicetoken,vendorid,phoneid,version,build,executable,bundle,lang)
request += '&timezoneoffset=%d' % 60        # local offset to UTC time
request += '&timeampm=%s' % ('true')        # 12h vs 24h clock
request += '&usecelsius=%s' % ('true')      # Celcius vs Fahrenheit
request += '&usemm=%s' % ('true')           # mm va in
request += '&speedunit=%d' % 0              # wind speed (0: m/s, 1: km/h, 2: mph, 3: kn)
request += '&timestamp=%s' % datetime.datetime.utcnow().strftime("%s")  # current UTC timestamp

requestMD5 = request + 'asdfaldfjadflxgeteeiorut0ß8vfdft34503580'  # SALT for the MD5
requestMD5 = requestMD5.replace('-','')
requestMD5 = requestMD5.replace(',','')
requestMD5 = requestMD5.replace('.','')
requestMD5 = requestMD5.lower()

m = hashlib.md5()
m.update(requestMD5)
hexdig = m.hexdigest()

request += '&requesttoken=%s' % hexdig

request += '&deviceids=%s' % ','.join(sensors)
#request += '&measurementfroms=%s' % ('0,' * len(sensors))
#request += '&measurementcounts=%s' % ('50,' * len(sensors))

http_header = {
                "User-Agent" : "remotemonitor/248 CFNetwork/758.2.8 Darwin/15.0.0",
                "Accept-Language" : "en-us",
                "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
                "Host" : "www.data199.com:8080",
                }

# create an urllib2 opener()
opener = urllib2.build_opener()

# create your HTTP request
req = urllib2.Request('http://www.data199.com:8080/api/v1/dashboard', request, http_header)

# submit your request
while True:
    res = opener.open(req)
    parseJSON(json.loads(res.read()))
    print '-' * 40
    time.sleep(10*60)   # wait for 10 minutes

Atari ST Book: Internal Registers

By looking at the ROM code, available software and the hardware layout I can now document most specialty registers in the ST Book from Atari. I hope it is useful to you. Also available at GitHub.

The main ROM for the ST Book starts at $e0000 and ends at $e3ffff (256kb large). At $e40000 starts the ROM-Disk (also 256kb large), which is automatically activated as drive P.

YM Port A

Bit Description
0 Side Select (S0SEL)
1 Disk 0 Select (D0SEL)
2 Disk 1 Select (D1SEL)
3 MAX241 Pin 20 (TI3) – RS232 RTS (/MFPRTS)
4 MAX241 Pin 6 (TI2) – RS232 DTR (/MFPDTR)
5 Centronics Strobe (STROBE)
6 IDE Reset (IDERESET)
7 FDD Dense Selection (FDD_DENSE_SEL)

Autovector Interrupt Level 7 /POWER FAIL (NMI)

MFP Input Pins

Bit Description
7 Power Alarms (Power Alarms) (POWER_ALARMS-) = (/SRCLOW /RTC_ALARM /POWERON)
6 MAX241 Pin 22 (RD4) – RS232 CD (/MFPRI)
5 XDISKINT
4 KTDK (VBL) (KTOK)
3 XBLTINT
2 MAX241 Pin 26 (RD3) – RS232 CTS (/MFPCTS)
1 MAX241 Pin 5 (RD2) – RS232 DCD (/MFPCD)
0 Centronics Busy (BUSY)

$D0000 – Unknown $D0004 – Unknown

$FF820B

Bit Description
0 0: enable combo -> shadow controller video transfer, 1: disable combo -> shadow controller video transfer

$FF827E

Bit Description
0 0: Shadow Chip OFF
1 0: /SHIFTER_OFF output (Unused in STBook)
2 0: POWER_OFF (Turns off main VCC when high)
3 0: /22ON output (turns off LCD Bias when HIGH)
4 0: REFRESH_MACHINE output (turns on refresh controller)
5 0: RS–232_OFF output (turns off +/- 10 generator)
6 0: (Unused in STBook)
7 0: MTR_POWER_ON (turns on IDE drive motor supply)

$FF9200 (Configuration/Signal register)

Bit Description
0 0: Power Button pressed /(POWER_SWITCH)
1 0: Top is closed /(TOP_CLOSED)
2 0: RTC Alarm triggered /(RTC_ALARM)
3 0: “Common Source” voltage level below 7.2V /(SOURCE_DEAD) – triggers an NMI
4 0: “Common Source” voltage level below 8.8V /(SOURCE_LOW)
5 0: External Modem (Pin 10 on J204) /(MODEM_WAKE)
6 Reserved (always 1)
7 0: Triggered from the Expansion Port /(EXPANSION_WAKE)
8 Reserved
9 Reserved
10 Reserved
11 Reserved
12 Reserved
13 SELF TEST (?)
14 LOW SPEED FLOPPY
15 DMA AVAILABLE

$FF9210 8-bit Common Power Voltage Level in 100mV steps

$FF9214 8-bit Reference Voltage Level in 100mV steps