OpenHAB
(Created page with "== openHAB Downloads == http://www.openhab.org/downloads.html == openHAB MiOS binding == https://github.com/openhab/openhab/tree/master/bundles/binding/org.openhab.binding....") |
(→Calculations) |
||
(15 intermediate revisions by one user not shown) | |||
Line 9: | Line 9: | ||
== Tools == | == Tools == | ||
− | === Creating | + | === Creating openHAB configuration files (items, sitemap, rrd4j persistence) === |
+ | Adjust unit_name and output_directory. | ||
+ | |||
+ | ==== items ==== | ||
https://github.com/openhab/openhab/wiki/Explanation-of-items | https://github.com/openhab/openhab/wiki/Explanation-of-items | ||
+ | Place *.items in: /openHAB/runtime/configurations/items | ||
+ | |||
+ | ==== sitemap ==== | ||
+ | https://github.com/openhab/openhab/wiki/Explanation-of-Sitemaps | ||
+ | |||
+ | Place *.sitemap in: /openHAB/runtime/configurations/sitemaps | ||
+ | |||
+ | ==== rrd4j persistence ==== | ||
+ | https://github.com/openhab/openhab/wiki/Persistence | ||
+ | |||
+ | [[Add]] rrd4j.persist_add to the Items section in /openHAB/runtime/configurations/persistence/rrd4j.persist and make sure that the strategies used are defined in the Strategies section. | ||
+ | |||
+ | ==== Luup code for MiOS devices ==== | ||
<source lang="text"> | <source lang="text"> | ||
− | local unit_name = 'house' | + | -- by Ap15e |
+ | |||
+ | local unit_name = 'house' | ||
+ | local output_directory = '/dataMine' | ||
local device_types = | local device_types = | ||
− | { [ 'urn:schemas-upnp-org:device:DimmableLight:1' | + | { [ 'urn:schemas-upnp-org:device:DimmableLight:1' ] = { 'Dimmer' , ' [%d]%' , '<slider>' , '/service/Dimming1/LoadLevelStatus,command:MAP(miosDimmerCommand.map)' }, |
− | [ 'urn:schemas-upnp-org:device:BinaryLight:1' | + | [ 'urn:schemas-upnp-org:device:BinaryLight:1' ] = { 'Switch' , '' , '' , '/service/SwitchPower1/Status,command:ON=SwitchPower1/SetTarget(newTargetValue=1)|OFF=SwitchPower1/SetTarget(newTargetValue=0),in:MAP(miosSwitchIn.map)' }, |
− | [ 'urn:schemas-micasaverde-com:device:TemperatureSensor:1' ] = { 'Number' , ' [%.1f °C]' , '<temperature>', '/service/TemperatureSensor1/CurrentTemperature' }, | + | [ 'urn:schemas-micasaverde-com:device:TemperatureSensor:1' ] = { 'Number' , ' [%.1f °C]', '<temperature>' , '/service/TemperatureSensor1/CurrentTemperature' }, |
− | [ 'urn:schemas-micasaverde-com:device:HumiditySensor:1' | + | [ 'urn:schemas-micasaverde-com:device:HumiditySensor:1' ] = { 'Number' , ' [%d]%' , '' , '/service/HumiditySensor1/CurrentLevel' }, |
− | [ 'urn:schemas-micasaverde-com:device:MotionSensor:1' | + | [ 'urn:schemas-micasaverde-com:device:MotionSensor:1' ] = { 'Contact', ' [%s]' , '<contact>' , '/service/SecuritySensor1/Tripped,in:MAP(miosContactIn.map)' }, |
− | [ 'urn:schemas-micasaverde-com:device:LightSensor:1' | + | [ 'urn:schemas-micasaverde-com:device:LightSensor:1' ] = { 'Number' , ' [%.2f]%' , '' , '/service/urn:micasaverde-com:serviceId:LightSensor1/CurrentLevel' }, |
− | [ 'urn:schemas-micasaverde-com:device:DoorSensor:1' | + | [ 'urn:schemas-micasaverde-com:device:DoorSensor:1' ] = { 'Contact', ' [%s]' , '<contact>' , '/service/SecuritySensor1/Tripped,in:MAP(miosContactIn.map)' }, |
− | [ 'urn:schemas-upnp-org:device:Heater:1' | + | [ 'urn:schemas-upnp-org:device:Heater:1' ] = { 'Number' , ' [%.1f °C]', '<temperature>' , '/service/urn:upnp-org:serviceId:TemperatureSetpoint1_Heat/CurrentSetpoint' }, |
− | [ 'urn:schemas-micasaverde-com:device:UvSensor:1' | + | [ 'urn:schemas-micasaverde-com:device:UvSensor:1' ] = { 'Number' , ' [%d]' , '' , '/service/urn:upnp-org:serviceId:UvSensor1/CurrentLevel' }, |
− | [ 'urn:schemas-micasaverde-com:device:RainSensor:1' | + | [ 'urn:schemas-micasaverde-com:device:RainSensor:1' ] = { 'Number' , ' [%.1f]' , '' , '/service/urn:upnp-org:serviceId:RainSensor1/CurrentTRain' }, |
− | [ 'urn:schemas-micasaverde-com:device:ScaleSensor:1' | + | [ 'urn:schemas-micasaverde-com:device:ScaleSensor:1' ] = { 'Number' , ' [%.1f]' , '' , '/service/urn:micasaverde-com:serviceId:ScaleSensor1/Weight' }, |
− | [ 'urn:schemas-micasaverde-com:device:BarometerSensor:1' | + | [ 'urn:schemas-micasaverde-com:device:BarometerSensor:1' ] = { 'Number' , ' [%.2f]hPa', '' , '/service/urn:upnp-org:serviceId:BarometerSensor1/CurrentPressure' }, |
+ | [ 'urn:schemas-micasaverde-com:device:WindSensor:1' ] = { 'Number' , ' [%.1f]' , '<wind>' , '/service/urn:upnp-org:serviceId:WindSensor1/AvgSpeed' }, | ||
+ | [ 'urn:schemas-micasaverde-com:device:SmokeSensor:1' ] = { 'Contact', ' [%s]' , '<contact>' , '/service/urn:upnp-org:serviceId:SmokeSensor1/Tripped,in:MAP(miosContactIn.map)' }, | ||
+ | [ 'urn:demo-micasaverde-com:device:weather:1' ] = { 'String' , ' [%s]' , '' , '/service/urn:micasaverde-com:serviceId:Weather1/Condition' }, | ||
+ | [ 'urn:schemas-ap15e-com:device:DAD' ] = { 'String' , ' [%s]' , '<sun>' , '/service/urn:upnp-ap15e-com:serviceId:DAD1/Sunrise_HHMMSS' }, | ||
+ | [ 'urn:schemas-micasaverde-com:device:WindowCovering:1' ] = { 'Switch' , '' , '<rollershutter>', '/service/SwitchPower1/Status,command:ON=SwitchPower1/SetTarget(newTargetValue=1)|OFF=SwitchPower1/SetTarget(newTargetValue=0),in:MAP(miosSwitchIn.map)' }, | ||
+ | [ 'urn:schemas-futzle-com:device:CurrentCostEnviR:1' ] = { 'Number' , ' [%d]' , '<energy>' , '/service/urn:micasaverde-com:serviceId:EnergyMetering1/Watts' }, | ||
+ | [ 'urn:schemas-futzle-com:device:CurrentCostEnviRAppliancePhase:1' ] = { 'Number' , ' [%d]' , '<energy>' , '/service/urn:micasaverde-com:serviceId:EnergyMetering1/Watts' }, | ||
+ | [ 'urn:schemas-futzle-com:device:CurrentCostEnviRAppliancePulse:1' ] = { 'Number' , ' [%d]' , '<energy>' , '/service/urn:micasaverde-com:serviceId:EnergyMetering1/Pulse' }, | ||
+ | [ 'urn:schemas-futzle-com:device:holidayvirtualswitch:1' ] = { 'Switch' , '' , '' , '/service/SwitchPower1/Status,command:ON=SwitchPower1/SetTarget(newTargetValue=1)|OFF=SwitchPower1/SetTarget(newTargetValue=0),in:MAP(miosSwitchIn.map)' } } | ||
+ | |||
+ | local device_categories = { | ||
+ | [1] = { 'Interface' }, | ||
+ | [2] = { 'Dimmable Light' }, | ||
+ | [3] = { 'Switch', { [1] = 'Interior', | ||
+ | [2] = 'Exterior', | ||
+ | [3] = 'In Wall' , | ||
+ | [4] = 'Refrigerator', | ||
+ | [5] = 'Garage Door' } }, | ||
+ | [4] = { 'Security Sensor', { [1] = 'Door Sensor', | ||
+ | [2] = 'Leak Sensor', | ||
+ | [3] = 'Motion Sensor', | ||
+ | [4] = 'Smoke Sensor', | ||
+ | [5] = 'CO Sensor', | ||
+ | [6] = 'Glass Break Sensor' } }, | ||
+ | [5] = { 'HVAC', { [1] = 'HVAC', | ||
+ | [2] = 'Heater' } }, | ||
+ | [6] = { 'Camera' }, | ||
+ | [7] = { 'Door Lock' }, | ||
+ | [8] = { 'Window Covering', { [1] = 'Window Covering', | ||
+ | [2] = 'ZRTSI' } }, | ||
+ | [9] = { 'Remote Control' }, | ||
+ | [10] = { 'IR Transmitter', { [1] = 'IR Transmitter', | ||
+ | [2] = 'USB UIRT' } }, | ||
+ | [11] = { 'Generic I/O' }, | ||
+ | [12] = { 'Generic Sensor' }, | ||
+ | [13] = { 'Serial Port' }, | ||
+ | [14] = { 'Scene Controller' }, | ||
+ | [15] = { 'A/V' }, | ||
+ | [16] = { 'Humidity Sensor' }, | ||
+ | [17] = { 'Temperature Sensor' }, | ||
+ | [18] = { 'Light Sensor' }, | ||
+ | [19] = { 'Z-Wave Interface' }, | ||
+ | [20] = { 'Insteon Interface' }, | ||
+ | [21] = { 'Power Meter' }, | ||
+ | [22] = { 'Alarm Panel' }, | ||
+ | [23] = { 'Alarm Partition' }, | ||
+ | [24] = { 'Siren' } } | ||
+ | |||
+ | group_written = {} | ||
+ | |||
function normalize_name( s ) | function normalize_name( s ) | ||
− | s = string.gsub( s or '', '[%s-/%.:]', '_' ) | + | s = string.gsub( s or '', '[%s-/%.:()]', '_' ) |
return '_' .. s | return '_' .. s | ||
end | end | ||
− | |||
− | + | function write_items() | |
− | + | ||
− | + | outf = io.open( output_directory .. '/' .. unit_name .. '.items', 'w\n' ) | |
− | + | ||
− | + | ||
− | + | outf:write( 'Group Rooms (All)\n' ) | |
+ | |||
+ | for k, v in pairs( luup.rooms ) | ||
+ | do | ||
− | + | outf:write( 'Group ' .. normalize_name( tostring( v ) ) .. ' "' .. tostring( v ) .. '" <' .. normalize_name( tostring( v ) ) .. '> (Rooms)\n' ) | |
− | + | ||
− | + | end | |
− | + | outf:write( 'Group _no_room "no room" <_no_room> (Rooms)\n' ) | |
− | luup. | + | for k, v in pairs(luup.devices) |
+ | do | ||
− | + | dt = device_types[ v.device_type ] | |
− | + | if dt ~= nil | |
+ | then | ||
− | + | c = device_categories[ v.category_num ] | |
− | + | ||
− | + | if c == nil | |
+ | then | ||
− | + | t = 'DEVICE CATEGORY ' .. tostring( v.category_num ) .. '/' .. tostring( v.subcategory_num ) | |
+ | |||
+ | else | ||
+ | |||
+ | t = c[ 1 ] | ||
+ | |||
+ | st = c[ 2 ] | ||
+ | |||
+ | if ( st ~= nil ) and ( v.subcategory_num ~= 0 ) | ||
+ | then | ||
+ | |||
+ | t = t .. ' / ' .. tostring( st[ v.subcategory_num ] or v.subcategory_num ) | ||
+ | |||
+ | end | ||
+ | |||
+ | end | ||
+ | |||
+ | tn = normalize_name( t ) | ||
+ | |||
+ | if group_written[ t ] == nil | ||
+ | then | ||
+ | |||
+ | outf:write( 'Group ' .. tostring( tn ) .. 's "' .. tostring( t ) .. 's" (Rooms)\n' ) | ||
+ | outf:write( 'Number ' .. tostring( tn ) .. 'sChartPeriod\n' ) | ||
+ | |||
+ | group_written[ t ] = tn | ||
+ | |||
+ | end | ||
+ | |||
+ | outf:write( tostring( dt[ 1 ] ) .. ' ' .. normalize_name( tostring( v.description ) ) .. ' "' .. tostring( v.description ) .. tostring( dt[ 2 ] ) .. '" ' .. tostring( dt[ 3 ] ) .. ' (' .. normalize_name( tostring( luup.rooms[ v.room_num ] ) ) .. ',' .. tostring( tn ) .. 's) {mios="unit:' .. tostring( unit_name ) .. ',device:' .. k .. tostring( dt[ 4 ] ) .. '"}\n' ) | ||
+ | |||
+ | end | ||
end | end | ||
+ | |||
+ | outf:close() | ||
+ | |||
+ | end -- function write_items() | ||
+ | |||
+ | |||
+ | function write_sitemap() | ||
+ | |||
+ | outf = io.open( output_directory .. '/' .. unit_name .. '.sitemap', 'w\n' ) | ||
+ | |||
+ | outf:write( 'sitemap ' .. unit_name .. ' label="Main Menu"\n' ) | ||
+ | outf:write( '{\n' ) | ||
+ | outf:write( ' Frame {\n' ) | ||
+ | outf:write( ' Group item=Rooms label="Rooms"\n' ) | ||
+ | outf:write( ' }\n' ) | ||
+ | |||
+ | for k, v in pairs( group_written ) | ||
+ | do | ||
+ | |||
+ | p = tostring( v ) .. 'sChartPeriod' | ||
+ | |||
+ | i = tostring( v ) .. 's' | ||
+ | |||
+ | outf:write( ' Frame {\n' ) | ||
+ | outf:write( ' Switch item=' .. p .. ' label="Chart Period" mappings=[0="Hour", 1="Day", 2="Week"]\n' ) | ||
+ | outf:write( ' Chart item=' .. i .. ' period=h refresh=6000 visibility=[' .. p .. '==0, ' .. p .. '=="Uninitialized"]\n' ) | ||
+ | outf:write( ' Chart item=' .. i .. ' period=D refresh=30000 visibility=[' .. p .. '==1]\n' ) | ||
+ | outf:write( ' Chart item=' .. i .. ' period=W refresh=30000 visibility=[' .. p .. '==2]\n' ) | ||
+ | outf:write( ' }\n' ) | ||
+ | |||
+ | end | ||
+ | |||
+ | outf:write( '}\n' ) | ||
+ | |||
+ | outf:close() | ||
+ | |||
+ | end -- persistence_rrd4j() | ||
+ | |||
+ | |||
+ | function write_persistence_rrd4j() | ||
+ | |||
+ | outf = io.open( output_directory .. '/rrd4j.persist_add', 'w' ) | ||
+ | |||
+ | for k, v in pairs( group_written ) | ||
+ | do | ||
+ | |||
+ | i = tostring( v ) .. 's' | ||
+ | |||
+ | outf:write( i .. '* : strategy = everyChange, everyMinute, restoreOnStartup\n' ) | ||
+ | |||
+ | end | ||
+ | |||
+ | outf:close() | ||
+ | |||
+ | end -- write_persistence_rrd4j() | ||
+ | |||
+ | |||
+ | write_items() | ||
+ | write_sitemap() | ||
+ | write_persistence_rrd4j() | ||
+ | |||
+ | </source> | ||
+ | |||
+ | === Creating openHAB rules === | ||
+ | |||
+ | https://github.com/openhab/openhab/wiki/Rules | ||
+ | |||
+ | |||
+ | [[WORK IN PROGRESS (non-functional demo)]] | ||
+ | |||
+ | Use a real computer to run the following code: | ||
+ | |||
+ | <source lang="text"> | ||
+ | -- by Ap15e | ||
+ | |||
+ | local json = require( 'dkjson' ) -- use a json parser that doesn't complain about empty arrays ... | ||
+ | local http = require( 'socket.http' ) | ||
+ | |||
+ | local url = 'http://192.168.178.116:3480/data_request?id=user_data' | ||
+ | |||
+ | function normalize_name( s ) | ||
+ | |||
+ | s = string.gsub( s or '', '[%s-/%.:]', '_' ) | ||
+ | return '_' .. s | ||
end | end | ||
+ | |||
+ | body, c, l, h = http.request( url ) | ||
+ | |||
+ | print( '// status line', l ) | ||
+ | print( '// h', h ) | ||
+ | print( '// c', c ) | ||
+ | |||
+ | print( '' ) | ||
+ | |||
+ | if c == 200 | ||
+ | then | ||
+ | |||
+ | local data = json.decode( body ) | ||
+ | |||
+ | for k, v in pairs( data.scenes ) | ||
+ | do | ||
+ | |||
+ | print( 'rule ' .. normalize_name( v.name ) ) | ||
+ | print( '// MiOS id: ' .. v.id ) | ||
+ | print( 'when' ) | ||
+ | |||
+ | if v.timers ~= nil | ||
+ | then | ||
+ | |||
+ | for i, j in pairs( v.timers ) | ||
+ | do | ||
+ | |||
+ | t = tonumber( j.type ) | ||
+ | |||
+ | if t == 1 | ||
+ | then | ||
+ | |||
+ | print( ' ', j.interval, ' // MiOS type 1' ) | ||
+ | |||
+ | else if t == 2 | ||
+ | then | ||
+ | |||
+ | print( ' ', j.days_of_week, j.time, ' // MiOS type 2' ) | ||
+ | |||
+ | else if t == 3 | ||
+ | then | ||
+ | |||
+ | print( ' ', '// ERROR: Not implemented - MiOS type 3' ) | ||
+ | |||
+ | else if t == 4 | ||
+ | then | ||
+ | |||
+ | print( ' ', j.abstime, ' // MiOS type 4' ) | ||
+ | |||
+ | else | ||
+ | |||
+ | print( '// ERROR: unknown timer, MiOS type: ', tostring( t ) ) | ||
+ | |||
+ | for x, y in pairs( j ) | ||
+ | do | ||
+ | |||
+ | print( '// ', x, y ) | ||
+ | |||
+ | end | ||
+ | |||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | end | ||
+ | |||
+ | end | ||
+ | |||
+ | if v.triggers ~= nil | ||
+ | then | ||
+ | |||
+ | for i, j in pairs( v.triggers ) | ||
+ | do | ||
+ | |||
+ | print( '// ' .. j.name ) | ||
+ | |||
+ | for x, y in pairs( j ) | ||
+ | do | ||
+ | print( ' //', x, y ) | ||
+ | end | ||
+ | |||
+ | end | ||
+ | |||
+ | end | ||
+ | |||
+ | print( 'then' ) | ||
+ | print( 'end' ) | ||
+ | print( '' ) | ||
+ | |||
+ | end | ||
+ | |||
+ | else | ||
+ | |||
+ | print( '//http error code:', c ) | ||
+ | |||
+ | end | ||
</source> | </source> | ||
+ | |||
+ | == Tips & Tricks == | ||
+ | |||
+ | === Synchronizing Vera's devices with openHAB === | ||
+ | |||
+ | Mount ~/openHAB/runtime/configurations/items on Vera (see http://forum.micasaverde.com/index.php/topic,16452.msg125963.html#msg125963) and write the items file via Apps -> Develop Apps -> Edit Startup Lua. | ||
+ | |||
+ | === Building a quarter wave ground plane antenna for Z-Wave === | ||
+ | |||
+ | ==== Parts needed ==== | ||
+ | |||
+ | 4x Amphenol B6351B1-ND3G-50 | ||
+ | |||
+ | Copper wire | ||
+ | |||
+ | 50 Ohm cable BNC male - BNC male | ||
+ | |||
+ | SMA male - BNC female adapter (for Vera3 with antenna mod) | ||
+ | |||
+ | U.FL female - BNC female pigtail cable and U.FL male coaxial connector SMD (for Aeon Z-Stick S2) | ||
+ | |||
+ | [[File:parts.jpg|400px]] | ||
+ | |||
+ | ==== Calculations ==== | ||
+ | |||
+ | length of radials/radiator = speed of light / frequency * velocity factor / 4 | ||
+ | |||
+ | For EU frequency: length = 299792458 m/s / 868420000 Hz * 0.95 / 4 = 8.2 cm | ||
+ | |||
+ | ==== Antenna ==== | ||
+ | |||
+ | [[File:antenna.jpg|200px]] | ||
+ | |||
+ | ==== Modifying the Aeon Z-Stick S2 ==== | ||
+ | |||
+ | [[File:z_stick_s2.jpg|400px]] | ||
+ | |||
+ | == Screenshots == | ||
+ | |||
+ | [[File:openHAB1.jpg|300px]] [[File:openHAB2.jpg|300px]] [[File:openHAB3.jpg|300px]] |
Latest revision as of 20:46, 26 January 2015
Contents |
[edit] openHAB Downloads
http://www.openhab.org/downloads.html
[edit] openHAB MiOS binding
https://github.com/openhab/openhab/tree/master/bundles/binding/org.openhab.binding.mios
[edit] Tools
[edit] Creating openHAB configuration files (items, sitemap, rrd4j persistence)
Adjust unit_name and output_directory.
[edit] items
https://github.com/openhab/openhab/wiki/Explanation-of-items
Place *.items in: /openHAB/runtime/configurations/items
[edit] sitemap
https://github.com/openhab/openhab/wiki/Explanation-of-Sitemaps
Place *.sitemap in: /openHAB/runtime/configurations/sitemaps
[edit] rrd4j persistence
https://github.com/openhab/openhab/wiki/Persistence
Add rrd4j.persist_add to the Items section in /openHAB/runtime/configurations/persistence/rrd4j.persist and make sure that the strategies used are defined in the Strategies section.
[edit] Luup code for MiOS devices
-- by Ap15e local unit_name = 'house' local output_directory = '/dataMine' local device_types = { [ 'urn:schemas-upnp-org:device:DimmableLight:1' ] = { 'Dimmer' , ' [%d]%' , '<slider>' , '/service/Dimming1/LoadLevelStatus,command:MAP(miosDimmerCommand.map)' }, [ 'urn:schemas-upnp-org:device:BinaryLight:1' ] = { 'Switch' , '' , '' , '/service/SwitchPower1/Status,command:ON=SwitchPower1/SetTarget(newTargetValue=1)|OFF=SwitchPower1/SetTarget(newTargetValue=0),in:MAP(miosSwitchIn.map)' }, [ 'urn:schemas-micasaverde-com:device:TemperatureSensor:1' ] = { 'Number' , ' [%.1f °C]', '<temperature>' , '/service/TemperatureSensor1/CurrentTemperature' }, [ 'urn:schemas-micasaverde-com:device:HumiditySensor:1' ] = { 'Number' , ' [%d]%' , '' , '/service/HumiditySensor1/CurrentLevel' }, [ 'urn:schemas-micasaverde-com:device:MotionSensor:1' ] = { 'Contact', ' [%s]' , '<contact>' , '/service/SecuritySensor1/Tripped,in:MAP(miosContactIn.map)' }, [ 'urn:schemas-micasaverde-com:device:LightSensor:1' ] = { 'Number' , ' [%.2f]%' , '' , '/service/urn:micasaverde-com:serviceId:LightSensor1/CurrentLevel' }, [ 'urn:schemas-micasaverde-com:device:DoorSensor:1' ] = { 'Contact', ' [%s]' , '<contact>' , '/service/SecuritySensor1/Tripped,in:MAP(miosContactIn.map)' }, [ 'urn:schemas-upnp-org:device:Heater:1' ] = { 'Number' , ' [%.1f °C]', '<temperature>' , '/service/urn:upnp-org:serviceId:TemperatureSetpoint1_Heat/CurrentSetpoint' }, [ 'urn:schemas-micasaverde-com:device:UvSensor:1' ] = { 'Number' , ' [%d]' , '' , '/service/urn:upnp-org:serviceId:UvSensor1/CurrentLevel' }, [ 'urn:schemas-micasaverde-com:device:RainSensor:1' ] = { 'Number' , ' [%.1f]' , '' , '/service/urn:upnp-org:serviceId:RainSensor1/CurrentTRain' }, [ 'urn:schemas-micasaverde-com:device:ScaleSensor:1' ] = { 'Number' , ' [%.1f]' , '' , '/service/urn:micasaverde-com:serviceId:ScaleSensor1/Weight' }, [ 'urn:schemas-micasaverde-com:device:BarometerSensor:1' ] = { 'Number' , ' [%.2f]hPa', '' , '/service/urn:upnp-org:serviceId:BarometerSensor1/CurrentPressure' }, [ 'urn:schemas-micasaverde-com:device:WindSensor:1' ] = { 'Number' , ' [%.1f]' , '<wind>' , '/service/urn:upnp-org:serviceId:WindSensor1/AvgSpeed' }, [ 'urn:schemas-micasaverde-com:device:SmokeSensor:1' ] = { 'Contact', ' [%s]' , '<contact>' , '/service/urn:upnp-org:serviceId:SmokeSensor1/Tripped,in:MAP(miosContactIn.map)' }, [ 'urn:demo-micasaverde-com:device:weather:1' ] = { 'String' , ' [%s]' , '' , '/service/urn:micasaverde-com:serviceId:Weather1/Condition' }, [ 'urn:schemas-ap15e-com:device:DAD' ] = { 'String' , ' [%s]' , '<sun>' , '/service/urn:upnp-ap15e-com:serviceId:DAD1/Sunrise_HHMMSS' }, [ 'urn:schemas-micasaverde-com:device:WindowCovering:1' ] = { 'Switch' , '' , '<rollershutter>', '/service/SwitchPower1/Status,command:ON=SwitchPower1/SetTarget(newTargetValue=1)|OFF=SwitchPower1/SetTarget(newTargetValue=0),in:MAP(miosSwitchIn.map)' }, [ 'urn:schemas-futzle-com:device:CurrentCostEnviR:1' ] = { 'Number' , ' [%d]' , '<energy>' , '/service/urn:micasaverde-com:serviceId:EnergyMetering1/Watts' }, [ 'urn:schemas-futzle-com:device:CurrentCostEnviRAppliancePhase:1' ] = { 'Number' , ' [%d]' , '<energy>' , '/service/urn:micasaverde-com:serviceId:EnergyMetering1/Watts' }, [ 'urn:schemas-futzle-com:device:CurrentCostEnviRAppliancePulse:1' ] = { 'Number' , ' [%d]' , '<energy>' , '/service/urn:micasaverde-com:serviceId:EnergyMetering1/Pulse' }, [ 'urn:schemas-futzle-com:device:holidayvirtualswitch:1' ] = { 'Switch' , '' , '' , '/service/SwitchPower1/Status,command:ON=SwitchPower1/SetTarget(newTargetValue=1)|OFF=SwitchPower1/SetTarget(newTargetValue=0),in:MAP(miosSwitchIn.map)' } } local device_categories = { [1] = { 'Interface' }, [2] = { 'Dimmable Light' }, [3] = { 'Switch', { [1] = 'Interior', [2] = 'Exterior', [3] = 'In Wall' , [4] = 'Refrigerator', [5] = 'Garage Door' } }, [4] = { 'Security Sensor', { [1] = 'Door Sensor', [2] = 'Leak Sensor', [3] = 'Motion Sensor', [4] = 'Smoke Sensor', [5] = 'CO Sensor', [6] = 'Glass Break Sensor' } }, [5] = { 'HVAC', { [1] = 'HVAC', [2] = 'Heater' } }, [6] = { 'Camera' }, [7] = { 'Door Lock' }, [8] = { 'Window Covering', { [1] = 'Window Covering', [2] = 'ZRTSI' } }, [9] = { 'Remote Control' }, [10] = { 'IR Transmitter', { [1] = 'IR Transmitter', [2] = 'USB UIRT' } }, [11] = { 'Generic I/O' }, [12] = { 'Generic Sensor' }, [13] = { 'Serial Port' }, [14] = { 'Scene Controller' }, [15] = { 'A/V' }, [16] = { 'Humidity Sensor' }, [17] = { 'Temperature Sensor' }, [18] = { 'Light Sensor' }, [19] = { 'Z-Wave Interface' }, [20] = { 'Insteon Interface' }, [21] = { 'Power Meter' }, [22] = { 'Alarm Panel' }, [23] = { 'Alarm Partition' }, [24] = { 'Siren' } } group_written = {} function normalize_name( s ) s = string.gsub( s or '', '[%s-/%.:()]', '_' ) return '_' .. s end function write_items() outf = io.open( output_directory .. '/' .. unit_name .. '.items', 'w\n' ) outf:write( 'Group Rooms (All)\n' ) for k, v in pairs( luup.rooms ) do outf:write( 'Group ' .. normalize_name( tostring( v ) ) .. ' "' .. tostring( v ) .. '" <' .. normalize_name( tostring( v ) ) .. '> (Rooms)\n' ) end outf:write( 'Group _no_room "no room" <_no_room> (Rooms)\n' ) for k, v in pairs(luup.devices) do dt = device_types[ v.device_type ] if dt ~= nil then c = device_categories[ v.category_num ] if c == nil then t = 'DEVICE CATEGORY ' .. tostring( v.category_num ) .. '/' .. tostring( v.subcategory_num ) else t = c[ 1 ] st = c[ 2 ] if ( st ~= nil ) and ( v.subcategory_num ~= 0 ) then t = t .. ' / ' .. tostring( st[ v.subcategory_num ] or v.subcategory_num ) end end tn = normalize_name( t ) if group_written[ t ] == nil then outf:write( 'Group ' .. tostring( tn ) .. 's "' .. tostring( t ) .. 's" (Rooms)\n' ) outf:write( 'Number ' .. tostring( tn ) .. 'sChartPeriod\n' ) group_written[ t ] = tn end outf:write( tostring( dt[ 1 ] ) .. ' ' .. normalize_name( tostring( v.description ) ) .. ' "' .. tostring( v.description ) .. tostring( dt[ 2 ] ) .. '" ' .. tostring( dt[ 3 ] ) .. ' (' .. normalize_name( tostring( luup.rooms[ v.room_num ] ) ) .. ',' .. tostring( tn ) .. 's) {mios="unit:' .. tostring( unit_name ) .. ',device:' .. k .. tostring( dt[ 4 ] ) .. '"}\n' ) end end outf:close() end -- function write_items() function write_sitemap() outf = io.open( output_directory .. '/' .. unit_name .. '.sitemap', 'w\n' ) outf:write( 'sitemap ' .. unit_name .. ' label="Main Menu"\n' ) outf:write( '{\n' ) outf:write( ' Frame {\n' ) outf:write( ' Group item=Rooms label="Rooms"\n' ) outf:write( ' }\n' ) for k, v in pairs( group_written ) do p = tostring( v ) .. 'sChartPeriod' i = tostring( v ) .. 's' outf:write( ' Frame {\n' ) outf:write( ' Switch item=' .. p .. ' label="Chart Period" mappings=[0="Hour", 1="Day", 2="Week"]\n' ) outf:write( ' Chart item=' .. i .. ' period=h refresh=6000 visibility=[' .. p .. '==0, ' .. p .. '=="Uninitialized"]\n' ) outf:write( ' Chart item=' .. i .. ' period=D refresh=30000 visibility=[' .. p .. '==1]\n' ) outf:write( ' Chart item=' .. i .. ' period=W refresh=30000 visibility=[' .. p .. '==2]\n' ) outf:write( ' }\n' ) end outf:write( '}\n' ) outf:close() end -- persistence_rrd4j() function write_persistence_rrd4j() outf = io.open( output_directory .. '/rrd4j.persist_add', 'w' ) for k, v in pairs( group_written ) do i = tostring( v ) .. 's' outf:write( i .. '* : strategy = everyChange, everyMinute, restoreOnStartup\n' ) end outf:close() end -- write_persistence_rrd4j() write_items() write_sitemap() write_persistence_rrd4j()
[edit] Creating openHAB rules
https://github.com/openhab/openhab/wiki/Rules
WORK IN PROGRESS (non-functional demo)
Use a real computer to run the following code:
-- by Ap15e local json = require( 'dkjson' ) -- use a json parser that doesn't complain about empty arrays ... local http = require( 'socket.http' ) local url = 'http://192.168.178.116:3480/data_request?id=user_data' function normalize_name( s ) s = string.gsub( s or '', '[%s-/%.:]', '_' ) return '_' .. s end body, c, l, h = http.request( url ) print( '// status line', l ) print( '// h', h ) print( '// c', c ) print( '' ) if c == 200 then local data = json.decode( body ) for k, v in pairs( data.scenes ) do print( 'rule ' .. normalize_name( v.name ) ) print( '// MiOS id: ' .. v.id ) print( 'when' ) if v.timers ~= nil then for i, j in pairs( v.timers ) do t = tonumber( j.type ) if t == 1 then print( ' ', j.interval, ' // MiOS type 1' ) else if t == 2 then print( ' ', j.days_of_week, j.time, ' // MiOS type 2' ) else if t == 3 then print( ' ', '// ERROR: Not implemented - MiOS type 3' ) else if t == 4 then print( ' ', j.abstime, ' // MiOS type 4' ) else print( '// ERROR: unknown timer, MiOS type: ', tostring( t ) ) for x, y in pairs( j ) do print( '// ', x, y ) end end end end end end end if v.triggers ~= nil then for i, j in pairs( v.triggers ) do print( '// ' .. j.name ) for x, y in pairs( j ) do print( ' //', x, y ) end end end print( 'then' ) print( 'end' ) print( '' ) end else print( '//http error code:', c ) end
[edit] Tips & Tricks
[edit] Synchronizing Vera's devices with openHAB
Mount ~/openHAB/runtime/configurations/items on Vera (see http://forum.micasaverde.com/index.php/topic,16452.msg125963.html#msg125963) and write the items file via Apps -> Develop Apps -> Edit Startup Lua.
[edit] Building a quarter wave ground plane antenna for Z-Wave
[edit] Parts needed
4x Amphenol B6351B1-ND3G-50
Copper wire
50 Ohm cable BNC male - BNC male
SMA male - BNC female adapter (for Vera3 with antenna mod)
U.FL female - BNC female pigtail cable and U.FL male coaxial connector SMD (for Aeon Z-Stick S2)
[edit] Calculations
length of radials/radiator = speed of light / frequency * velocity factor / 4
For EU frequency: length = 299792458 m/s / 868420000 Hz * 0.95 / 4 = 8.2 cm