Skip to content

Instantly share code, notes, and snippets.

@WoLpH WoLpH/__init__.py
Last active Oct 13, 2016

Embed
What would you like to do?
RFXtrx
# -*- coding: utf-8 -*-
#
# This file is a plugin for EventGhost.
# Copyright (C) 2012 Walter Kraembring <krambriw>.
#
# ALL RIGHTS RESERVED. The development of this software is based on information
# provided by RFXCOM and is protected under Netherlands Copyright Laws and
# Treaties and shall be subject to the exclusive jurisdiction of the Netherlands
# Courts.
# This pluginís source code and other versions eventually based on it may be
# used exclusively to interface with RFXCOM products only. Any other usage of
# information in this source code is prohibited without express written
# permission from RFXCOM.
#
###############################################################################
#
# EventGhost is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 2 as published by the
# Free Software Foundation;
#
# EventGhost is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
#
# Acknowledgements: Part of code and some ideas are based on the serial plugin
#
##############################################################################
# Revision history:
#
# 2016-08-13 Walter Kraembring: Added support for FW release 433_1006
# 08-08-2016
# - Lighting5 - MDRemote 108 LED added
# - Unit code added to BlindsT3
# - FAN ñ SEAV TXS4 added
# 2016-05-08 Walter Kraembring: Added support for FW release 433_1002
# 06-05-2016
# - BlindsT12 ñ Confexx unit code corrected
# - Cartelectronic TIC and Encoder added
# - Livolo dim/scene commands added for On/Off
# module
# - RFY unit code All changed to channel 0
# 2016-03-12 Walter Kraembring: Added support for FW release 433_1001
# 18-02-2016
# - IT (Intertek,FA500,PROmaxÖ)
# - Confexx CNF24-2435 blind motors
# 2016-02-07 Walter Kraembring: Added support for FW release 433_95/195/251
# 06-02-2016
# - LucciAir Fan
# - Inovalley S80 plant humidity sensor
# - ASP blind motors
# - Avantek
# - HQ_COCO_20
# - Viking 02813 (reported as 02811)
# 2015-11-07 Walter Kraembring: Added support for Legrand CAD
# 2015-09-20 Walter Kraembring: Added support for Home Confort TEL-010
# Improved support for PT2262:
# - Action send_ELRO_Flamingo_Phenix_Sartano_
# RisingSun_Brennenstuhl renamed to
# send_PT2262
# - decoding PT2262 (Lighting4) now includes
# pulse timing value
# 2015-09-02 Walter Kraembring: Modified to support RFXtrx433E FW release
# 433_247 and RFXtrx433 Type1/Type2
# FW release 433_91/191.
# Now supporting:
# - ASA blinds
# - RGB 432W
# - Thermostat Mertik G6R-H4S
# 2015-06-05 Walter Kraembring: Added support for setting sensor lost
# timeouts from external script added
# 2015-03-21 Walter Kraembring: Support added for:
# - SelectPlus Action chime changed
# - Alecto WS4500 and compatibles
# - Envivo ENV-1348 Aldi chime
# - DEA Systems receivers (KeeLoq Classic raw)
# - Sunpery & Dolat DLM-1 blinds
# - La Crosse TX5 Rain gauge
# - Thermostat Mertik G6R-H4TD
# 2015-02-11 Walter Kraembring: Added monitoring of RFXtrx connection state:
# - Generates an event if connection is lost.
# Disabling/enabling of plugin should be
# enough to recover once the device is
# correctly re-connected and recognized by
# the operating system
# 2015-02-01 Walter Kraembring: Support added/updated for:
# - ELEC3 ìinstant power onlyî packets
# - Byron SX sound detection/selections
# 2015-01-11 Walter Kraembring: Support added for:
# - TEMP7 - Proove TSS330 and TH9 ñ TSS320
# - BlindsT8 Chamberlain CS4330CN
# - Chime SelectPlus200689101 and 200689103
# - Proove outdoor sensors TEMP7 type 311346
# and TH9 type 311501
# - Genuine device validation & copyright
# message added for fw versions 81/182/235
# and later
# 2014-12-27 Walter Kraembring: Support added for:
# - Livolo Appliance 1-10
# - Somfy RFY commands Enable sun+wind &
# Disable sun (RFXtrx433E only)
# - Smartwares radiator valves (RFXtrx433E
# only)
# - Alecto WS1700 and compatibles
# - Changed from old Websocket suite to support
# the new Webserver plugin with websocket
# included.
# 2014-10-01 Walter Kraembring: Now supporting:
# - Thermostat1 Digimax
# - Thermostat3 Mertik-Maxitrol G6R-H4 types
# 2014-09-19 Walter Kraembring: Modified to support RFXtrx433E FW release
# 433_230 and RFXtrx433 Type1/Type2
# FW release 433_79/179.
# Now supporting:
# - THB1 ñ BTHGN129 device
# - Chime ñ Byron MP001 transmit
# - TEMP11 ñ WT0122 pool sensor
# - Lighting5 ñ Eurodomest (NL ñ Action)
# - TRC02_2 RGB LED controller (this version
# has 3 batteries in the remote, TRC02 has
# only 2)
# 2014-08-22 Walter Kraembring: Added support for date/time sensor RTGR328N
# 2014-07-30 Walter Kraembring: Modified to support RFXtrx433E FW release
# 433_229 25-07-2014 and RFXtrx433 Type1/Type2
# FW release 433_78/178 25-07-2014
# - Lighting5 - Aoke 1 channel relay with
# learning code
# 2014-07-14 Walter Kraembring: Modified to support RFXtrx433E FW release
# 433_227 25-06-2014 and RFXtrx433 Type1/Type2
# FW release 433_77 26-06-2014
# - BlindsT8 ñ RFY added new action to support
# Venetian blinds
# 2014-06-06 Walter Kraembring: Modified to support RFXtrx433E FW release
# 433_226 29-05-2014 and RFXtrx433 Type1/Type2
# FW release 433_76 29-05-2014
# - Imagintronix soil sensor added
# - Kambrook RF3672 added, supported by Type 2
# (used in Australia)
# - BlindsT8 ñ RFY added
# Bugfix in calculation of wind average speed
# and gust
# 2014-04-24 Walter Kraembring: Modified to support FW version 74
# - Blinds - ID4 added
# - BlindsT4 - unit number set to zero
# - BlindsT7 - Forest unit number selection
# corrected
# 2014-04-08 Walter Kraembring: Added support for
# - Lighting1: Energenie 5-gang
# - Lighting1: COCO GDR2-2000R
# - BlindsT6: DC106/Rohrmotor24-RMF/Yooda
# - BlindsT7 - Forest
# 2014-02-16 Walter Kraembring: Improved action to dim AC devices up/down in
# defined step size
# 2014-02-14 Walter Kraembring: Made event prefix configurable (to support
# multiple RFXtrx devices)
# Added action to dim AC devices up/down in
# defined step size
# Saving the dim level persistent
# 2014-01-30 Walter Kraembring: Support for websockets by the Tornado plugin
# 2013-12-28 Walter Kraembring: Added action for resetting the state memory
# Modified action for resetting the sensor
# state memory
# Added action to map remote control address
# 2013-12-12 Walter Kraembring: Added support for
# - RGB TRC02 controllers
# 2013-11-18 Walter Kraembring: Added support for
# - Maverick ET-732
# - Alecto SA30
# - Oregon EW109
# - ELEC5 Revolt
# - Changed configuration view, use RFXmngr to
# enable/disable selected protocols
# Some bug fixes for:
# - ATI, Medion, PC Remote
# - CM113
# - RollerTrol, Hasta, A-OK, Raex, Media Mount
# 2013-10-29 Walter Kraembring: Added actions to support
# - Siemens SF01 LF959RA50/LF259RB50/LF959RB50
# extractor hood transmit
# - Livolo transmit
# 2013-10-04 Walter Kraembring: Added actions to enable/disable undecoded
# messages.
# 2013-09-30 Walter Kraembring: Lighting5 LWRF Colour commands added
# Alecto WS1200 added
# Byron SX Chime added
# 2013-06-11 Walter Kraembring: RAEX ID changed to 3 bytes, Unit code is 0.
# Added support for MDREMOTE LED dimmer,
# Conrad RSL2 and Energenie.
# 2013-05-09 Walter Kraembring: Modified the settings for RAEX motor, also
# corrections made for Media Mount commands.
# Added support for ELRO, Flamingo, Phenix,
# Sartano, RisingSun, Brennenstuhl (Lighting4).
# 2013-03-14 Walter Kraembring: Blyss group code until P added.
# Action to decode test messages added.
# 2013-02-16 Walter Kraembring: Action to gradually dim AC devices added.
# 2013-02-12 Walter Kraembring: Blyss group code E added.
# Rubicson temperature and humidity sensor
# added.
# Media Mount projection screen added
# (transmission only).
# RFXtrx type 1 and 2 detection added.
# 2013-01-16 Walter Kraembring: Management of sensors lost/back improved and
# information sent via websocket.
# 2013-01-12 Walter Kraembring: Further improved broken message handling,
# trying to repair broken messages. Now I am
# pleased with the solution.
# Support for Raex YR1326 T16 motor added.
# Modified settings for ByeByeStandBy (units
# 1-6 are now possible).
# 2012-11-14 Walter Kraembring: Update to comply with FW release 433_56.
# - Meiantech/Atlantic/Aidebao IR beam added
# - decoding of Koppla removed (sending still
# possible)
# - Current/Energy meter CM180i added
# - RFXsensor added
# - unit codes for A-OK set to '00'
# - possible ID's for BLINDS1 adjusted
# 2012-10-21 Walter Kraembring: Update to comply with FW release 433_55:
# A-OK RF01, A-OK AC114 and new ByeByeStandBy
# models. Some other minor improvements.
# 2012-10-04 Walter Kraembring: Added support to send keys as simulated
# remote (ATI, Medion and PC Remote).
# 2012-10-02 Walter Kraembring: Added support receiving from remotes ATI,
# Medion, PC Remote.
# 2012-09-24 Walter Kraembring: Added support for HE105 and RTS10.
# 2012-09-13 Walter Kraembring: Added support for OWL CM113.
# Reduced printouts to the log window, keeping
# it a bit cleaner. Enable debug to get more
# info in the log window.
# Fixed bugs in 0x12(Koppla), 0x20(X10 remote),
# 0x57(UV..).
# Changed key handling for web sockets data.
# 2012-08-28 Walter Kraembring: Improved message handling, trying to repair
# broken messages.
# TFA 30.3133 added
# 2012-08-18 Walter Kraembring: Update to comply with FW release 433_48:
# Philips SBC, Blyss/Thompson, Hasta old added,
# BLINDS1 Set Limit command added.
# 2012-08-14 Walter Kraembring: Added actions for dimming Good Morning and
# Good Night lamps (works with AC devices like
# NEXA with support for setting dim levels).
# 2012-07-24 Walter Kraembring: Meiantech commands added
# Bugfixes in decoding of 0x12, 0x14, 0x18,
# 0x19 and 0x20
# 2012-07-16 Walter Kraembring: Update to comply with FW release 433_46:
# Viking 02035, 02038 added, RUBiCSON added,
# Security1 tamper status commands changed,
# Meiantech added.
# Improved websocket startup methods.
# 2012-07-07 Walter Kraembring: Added support for the RFXMeter and RFXPower
# Added support for the La Crosse WS2300
# Reworked the message handling again, not
# using the eg.SerialThread anymore.
# 2012-06-27 Walter Kraembring: Added support for websockets (requires the
# websocket suite plugin to be added to your
# configuration.)
# Added support for OWL CM119/160 and
# UV sensors UVN128, UV138, UVN800, TFA
# 2012-05-29 Walter Kraembring: Added support for RisingSun, RollerTrol and
# Viking 02811
# Bug fixed for AC (unit codes 1-16)
# 2012-05-09 Walter Kraembring: Suppress/Allow duplicated events selectable
# 2012-05-04 Walter Kraembring: X10 decoding of received bright/dim commands
# fixed.
# 2012-04-29 Walter Kraembring: This version supports:
# - Wind directions as text information
# (S, N, E, W etc).
# - Rain total values are divided by 10
# (requiresFW version 35 and later).
# - TEMP6 - TS15C.
# - UPM/ESIC wind & rain sensors.
# 2012-04-15 Walter Kraembring: This version is using the eg.SerialThread.
# Improved performance, simplified the code.
# Changed the calculation of temperature from
# temperature sensors.
# 2012-04-13 Walter Kraembring: Improved automatic naming of macros.
# 2012-04-11 Walter Kraembring: Added selection of supported protocols.
# Improved reading and decoding from COM port.
# Improved automatic naming of macros.
# Cosmetic bug fixing in some action
# configuration dialogs.
# 2012-04-02 Walter Kraembring: First official version.
##############################################################################
import eg, wx
import time, os
from threading import Event, Thread
from codecs import getdecoder
import collections
eg.RegisterPlugin(
name="RFXtrx",
author="krambriw",
guid="{72DCE030-68FF-49B9-835D-295D4CF048ED}",
version="1.9.9",
canMultiLoad=True,
kind="external",
description=(
"RFXtrx communication through a virtual serial port."
'<br\n><br\n>'
'<center><img src="rfxtrx.png" /></center>'
),
url="http://www.eventghost.net/forum",
)
DEVICES = (
'040',
'042',
'04E',
'04F',
'050',
'051',
'052',
'054',
'055',
'056',
'057',
'058',
'059',
'05A_1',
'05A_2',
'05B',
'05C',
'060_01',
'060_02',
'070',
'071',
'020',
)
class Text:
port = "Port:"
logToFile = "Log events to file"
debugInfo = "Show debug info"
macroNames = "Automatic naming of macros"
dupEvents = "Allow duplicated events"
set_prefix = "Configure the event prefix"
use_websockets = "Use Webserver plugin with websocket support (port 1234) "
use_tornadoWebsockets = "Use Tornado plugin for websockets "
decode_advice = (
"Please select the required protocols with the RFXmngr application"
)
decodeError = "Decoding of message failed: "
fwVersion = "RFXtrx Firmware Version: "
rfxtrx = "RFXtrx receiver/transceiver type: "
rfxtrx_type = "You have a RFXtrx Type "
rfxtrx_fw = "You have firmware type: "
messageT = "Wrong command response, your RFXtrx type might not support this "
messageL = "Wrong message length: "
unknown_RFY_remote = "Unknown RFY remote"
no_extended_hardware_present = "No extended hardware present (RFY)"
rfxtrx_started = "A genuine RFXtrx is detected and started"
rfxtrx_lost = "Lost connection with the RFXtrx"
messageDbg = "Debug Info: "
messageUC = "Message broken and repaired within"
messageNP = "Message could not be repaired"
messageUKnwn = "Unknown message: "
messageWebSocketError = "Websocket error...check that the plugin is added to your configuration "
messageWebSocketBroadcastError = "Websocket broadcast error...check the websocket configuration "
disconnecting = "Stopping and disconnecting the RFXtrx device...please wait"
cleanUpmonitoring = "Cleaning up monitoring tasks..."
readyStopped = "Plugin successfully stopped"
threadStopped = "Receiving thread is stopped..."
dt_threadStopped = "Date & Time thread ended"
ka_threadStopped = "Keep Alive thread ended"
keyAdded = "Key added to dictionary"
textBoxName = "Enter a descriptive name for the action"
textBoxLCdeviceId = "Select the ID of the La Crosse TX5 rain gauge to reset the collected rain data"
textBoxProtocol = "Select the device protocol to be used"
textBoxHouseCode = "Select the house code of the device"
textBoxGroupCode = "Select the group code of the device"
textBoxDeviceCode = "Select the device code of the device"
textBoxCommand = "Select the command to send"
textBoxColor = (
"If your command is 'Select Color', then also select the color code from below"
)
textBoxAddress = "Type/paste the unit address to be used (from 00 00 00 01 to 03 FF FF FF)"
textBoxDeviceUnit = "Select the unit code of the device"
textBoxLevel = "Select the dim/bright level"
textBoxStepSize = "Select the dim step size"
textBoxStatus = "Select status"
textBoxMode = "Select mode"
textBoxTemperature = "Set the temperature"
textBoxSetPoint = "Set the setpoint"
timeInBetween_txt = "Select the time delay between dim level commands"
timeToWakeUp_txt = "Total snooze time (minutes): "
timeToSleep_txt = "Total snooze time (minutes): "
textBoxSystem = "Select the system code to use"
textChannel = "Check the boxes for the channels to use"
textBoxDeviceID = "Select the proper ID selections"
textBoxPulseTiming = "Set the proper pulse timing (default 350 us)"
textBoxIdCommands = "Check the boxes for the id and command"
textStep_up = "Check the box to dim up "
txt_signal_back = "Recovered contact with sensor"
txt_taskObj = "Lost contact with sensor"
class CurrentStateData(eg.PersistentData):
current_state_memory = {}
sensors_status = {}
rfxSensors = {}
dimGradually = {}
dimStepWise = {}
cmndSeqNbr_015 = 0
remote_address_map = {}
totalRain = {}
class RFXtrx(eg.RawReceiverPlugin):
text = Text
def __init__(self):
self.current_state_memory = CurrentStateData.current_state_memory
self.sensors_status = CurrentStateData.sensors_status
self.dimGradually = CurrentStateData.dimGradually
eg.RawReceiverPlugin.__init__(self)
self.AddAction(send_AC)
self.AddAction(DimGradually_AC)
self.AddAction(DimStepWise_AC)
self.AddAction(GoodMorning_AC)
self.AddAction(GoodNight_AC)
self.AddAction(send_Kambrook)
self.AddAction(send_ARC)
self.AddAction(send_Waveman)
self.AddAction(send_Chacon_EMW200)
self.AddAction(send_IMPULS)
self.AddAction(send_RisingSun)
self.AddAction(send_ByeByeStandBy)
self.AddAction(send_Philips_SBC)
self.AddAction(send_Energenie)
self.AddAction(send_COCO_GDR2_2000R)
self.AddAction(send_HQ_COCO_20)
self.AddAction(send_Energenie_5g)
self.AddAction(send_Siemens_Lightwave_RF)
self.AddAction(send_Siemens_SF01)
self.AddAction(send_LucciAir)
self.AddAction(send_SEAV_TXS4)
self.AddAction(send_PT2262)
self.AddAction(send_EMW100_GAO_Everflourish)
self.AddAction(send_Conrad_RSL2)
self.AddAction(send_MDREMOTE_LED)
self.AddAction(send_Aoke_Relay)
self.AddAction(send_IT_Intertek)
self.AddAction(send_Legrand_CAD)
self.AddAction(send_RGB_TRC02)
self.AddAction(send_RGB_TRC02_2)
self.AddAction(send_RGB432W)
self.AddAction(send_Eurodomest)
self.AddAction(send_Avantek)
self.AddAction(send_Blyss_Thomson)
self.AddAction(send_Byron_SX)
self.AddAction(send_Byron_MP001)
self.AddAction(send_SelectPlus)
self.AddAction(send_Envivo)
self.AddAction(send_ELRO_AB400D)
self.AddAction(send_Livolo)
self.AddAction(send_Livolo_Appliance)
self.AddAction(send_X10)
self.AddAction(send_Koppla)
self.AddAction(send_Harrison_Curtain)
self.AddAction(send_RollerTrol)
self.AddAction(send_Confexx)
self.AddAction(send_A_OK)
self.AddAction(send_Raex)
self.AddAction(send_Media_Mount)
self.AddAction(send_DC_Forest)
self.AddAction(send_Chamberlain)
self.AddAction(send_Sunpery)
self.AddAction(send_Dolat_DLM_1_Topstar)
self.AddAction(send_ASP)
self.AddAction(send_RFY)
self.AddAction(send_RFY_ext)
self.AddAction(send_RFY_Venetian)
self.AddAction(send_ASA)
self.AddAction(send_KeeLoq_Classic)
self.AddAction(send_x10_security_remote)
self.AddAction(send_KD101_smoke_detector)
self.AddAction(send_SA30_smoke_detector)
self.AddAction(send_Meiantech)
self.AddAction(send_Digimax)
self.AddAction(send_Thermostat_HE105)
self.AddAction(send_Thermostat_RTS10)
self.AddAction(send_Smartwares_radiator_valve)
self.AddAction(send_Mertik_G6R_H4T1)
self.AddAction(send_Mertik_G6R_H4TB)
self.AddAction(send_Mertik_G6R_H4TD)
self.AddAction(send_Mertik_G6R_H4S)
self.AddAction(send_ATI_RemoteWonder)
self.AddAction(send_ATI_RemoteWonderPlus)
self.AddAction(send_Medion_Remote)
self.AddAction(send_Home_Confort)
self.AddAction(send_X10_PC_Remote)
self.AddAction(WebRefresh)
self.AddAction(remote_address_Mapper)
self.AddAction(ClearSensorsStatus)
self.AddAction(ResetCurrentStatus)
self.AddAction(ResetLaCrosseTX5_data)
self.AddAction(disable_unDecoded)
self.AddAction(enable_unDecoded)
self.AddAction(max_outPower)
self.AddAction(normal_outPower)
self.AddAction(decode_Test_Message)
def __start__(
self,
port=0,
bLogToFile=False,
bDebug=False,
b01=True,
b02=True,
b03=True,
b04=True,
b05=True,
b06=True,
b07=True,
b08=True,
b09=True,
b0a=True,
b0b=True,
b0c=True,
b0d=True,
b0e=True,
b0f=True,
mMacroNames=True,
bDupEvents=False,
websocket_port_nbr=1234,
use_websockets=False,
b10=True,
use_tornadoWebsockets=False,
prefix='RFXtrx'
):
self.init = True
self.prefix = prefix
self.fwVer = 54
self.bLogToFile = bLogToFile
self.bDebug = bDebug
self.deviceCheck = False
self.sensorLostTimeOut = 600.0
self.decoder_mems = collections.defaultdict(dict)
self.monitor_mems = collections.defaultdict(dict)
self.usage_05A_2 = '0.00'
self.mMacroNames = mMacroNames
self.bDupEvents = bDupEvents
self.use_websockets = use_websockets
self.websocket_port_nbr = str(websocket_port_nbr)
self.use_tornadoWebsockets = use_tornadoWebsockets
self.rfxSensors = CurrentStateData.rfxSensors
self.tmpMessage = ''
self.tmpMilliSec = 0
self.flipCount = {}
self.flCount_prev = {}
self.totalRain = CurrentStateData.totalRain
self.pmh = None
self.interfaceMode = []
self.keepAliveThreadEvent = Event()
self.remain = 0.0
keepAliveThread = Thread(
target=self.keep_Alive,
args=(self.keepAliveThreadEvent,)
)
keepAliveThread.start()
self.dateTimeThreadEvent = Event()
dateTimeThread = Thread(
target=self.date_Time,
args=(self.dateTimeThreadEvent,)
)
dateTimeThread.start()
try:
self.serial = eg.SerialPort(
port=port,
baudrate=38400,
bytesize=8,
stopbits=1,
parity='N',
xonxoff=0,
rtscts=0,
)
except:
self.serial = None
raise self.Exceptions.SerialOpenFailed
self.serial.timeout = 0.01
self.serial.setRTS()
# Reset connection
reset_str = "0D 00 00 00 00 00 00 00 00 00 00 00 00 00"
self.WriteMsg(reset_str, '', '')
eg.Wait(2.0)
# Flush the COM port receive buffer
self.serial.flushInput
# Get device status
get_status_str = "0D 00 00 01 02 00 00 00 00 00 00 00 00 00"
self.WriteMsg(get_status_str, '', '')
# Check valid RFXCOM device
chk_valid_device = "0D 00 00 02 07 00 00 00 00 00 00 00 00 00"
self.WriteMsg(chk_valid_device, '', '')
# Start the communication thread
self.decoder = getdecoder(eg.systemEncoding)
self.info.eventPrefix = self.prefix
self.finished = Event()
self.receiveThread = Thread(
target=self.ReceiveThread,
name="RFXtrxThread"
)
self.receiveThread.start()
def __stop__(self):
print self.text.disconnecting
self.dateTimeThreadEvent.set()
self.keepAliveThreadEvent.set()
if self.serial is not None:
if self.receiveThread:
self.receiveThread.join(1.0)
self.finished.set()
time.sleep(0.1)
try:
self.serial.close()
except:
pass
self.serial = None
try:
eg.scheduler.CancelTask(self.pmh)
except:
pass
print self.text.cleanUpmonitoring
for device in DEVICES:
for task in self.monitor_mems[device].values():
try:
eg.scheduler.CancelTask(task)
except:
pass
eg.Wait(self.remain + 0.5)
print self.text.readyStopped
def ClearTempMessage(self):
eg.PrintError(
self.text.messageNP +
' ' +
self.tmpMessage
)
self.tmpMessage = ''
self.tmpMilliSec = 0
def CancelTask(self, handle):
try:
eg.scheduler.CancelTask(handle)
except:
pass
def MilliSeconds(self):
return int(round(time.time() * 1000))
def PartialMessageHandler(self, data): # Uncompleted message arrives
# Start time measuring
if not self.tmpMilliSec > 0:
self.tmpMilliSec = self.MilliSeconds()
# Cancel resetting task if already scheduled
self.CancelTask(self.pmh)
# Schedule the new resetting task
self.pmh = eg.scheduler.AddTask(0.5, self.ClearTempMessage)
# Add the received data to the temporary storage
self.tmpMessage += data
if self.bDebug:
print self.tmpMessage
# Check length and if it has become completed
# If not, just wait for the remainer
messageL = int(self.tmpMessage[0:2], 16)
if len(self.tmpMessage) == (messageL + 1) * 2:
# Cancel scheduled task and clear the temporary storage
self.CancelTask(self.pmh)
# Forward the repaired message for normal processing
self.HandleChar(self.tmpMessage)
if self.bDebug:
timeToRepair = self.MilliSeconds() - self.tmpMilliSec
eg.PrintError(
self.text.messageUC +
' ' +
str(timeToRepair) +
' ms' +
' ' +
self.tmpMessage
)
self.tmpMessage = ''
self.tmpMilliSec = 0
def ReceiveThread(self):
out = ''
while not self.finished.isSet():
time.sleep(0.005) # Release CPU
while self.serial.inWaiting() > 0 and not self.hold:
self.finished.wait(0.01)
buf = self.serial.read(1)
if len(str(out)) == 0:
pl = int('0x' + str(buf.encode('hex')), 0)
out += buf
out += self.serial.read(pl)
data = str(out.encode('hex'))
if pl > 3 and len(str(out)) == pl + 1:
if self.bDebug:
print "Debug Info: ", data
self.HandleChar(data)
else:
self.PartialMessageHandler(data)
out = ''
print self.text.threadStopped
def date_Time(self, dateTimeThreadEvent):
counter = int(time.strftime("%S", time.localtime()))
while not dateTimeThreadEvent.isSet():
if counter == 60:
self.DateAndTimeInfo()
counter = 1
else:
counter += 1
dateTimeThreadEvent.wait(1.0)
print self.text.dt_threadStopped
def keep_Alive(self, keepAliveThreadEvent): # Keep Alive Loop
counter = 0
while not keepAliveThreadEvent.isSet():
if counter == 60:
# self.KeepAlive()
counter = 0
else:
counter += 1
keepAliveThreadEvent.wait(1.0)
print self.text.ka_threadStopped
def DateAndTimeInfo(self):
if self.use_websockets or self.use_tornadoWebsockets:
currDate_Time = str(
time.strftime(
"%w %Y-%m-%d %H:%M",
time.localtime()
)
)
msg = "currDate_Time." + currDate_Time
self.BroadcastMessage(msg)
self.deviceCheck = True
chk_valid_device = "0D 00 00 01 02 00 00 00 00 00 00 00 00 00"
self.WriteMsg(chk_valid_device, '', '')
def KeepAlive(self):
if self.use_websockets or self.use_tornadoWebsockets:
msg = "KeepAlive"
self.BroadcastMessage(msg)
def StatusRefresh(self):
if self.use_websockets or self.use_tornadoWebsockets:
if len(self.current_state_memory) > 0:
for i in self.current_state_memory:
msg = self.current_state_memory[i]
self.BroadcastMessage(msg)
time.sleep(0.01)
if len(self.sensors_status) > 0:
for i in self.sensors_status:
msg = self.sensors_status[i]
self.BroadcastMessage(msg)
time.sleep(0.01)
def SavePersistent(self, msg, m_key):
# Check if the message comes from a remote that shall be re-mapped
m_k = m_key.split(' ')
if len(m_k) == 3:
m = msg.split(' ')
try:
adr_new = CurrentStateData.remote_address_map[m_k[1]]
m_key = m_k[0] + ' ' + adr_new + ' ' + m_k[2]
msg = (
m[0] + ' ' + m[1] + ' ' + m[2] + ' ' + adr_new + ' ' +
m[4] + ' ' + m[5] + ' ' + m[6] + ' ' + m[7] + ' ' +
m[8] + ' ' + m[9] + ' ' + m[10] + ' ' + m[11] + ' ' +
m[12] + ' ' + m[13]
)
except KeyError:
pass
# Make status data persistent if it has changed
try:
if msg != self.current_state_memory[m_key]:
self.current_state_memory[m_key] = msg
self.BroadcastMessage(msg)
elif self.bDupEvents:
self.BroadcastMessage(msg)
except KeyError:
if self.bDebug:
print self.text.keyAdded
self.current_state_memory[m_key] = msg
self.BroadcastMessage(msg)
def BroadcastMessage(self, msg):
if self.use_websockets:
try:
p = eg.plugins.Webserver.BroadcastMessage(
msg.encode('utf-8'),
False
)
if p <> None:
print self.text.messageWebSocketBroadcastError
except:
print self.text.messageWebSocketError
time.sleep(1.0)
if self.use_tornadoWebsockets:
try:
p = eg.plugins.Tornado.BroadcastMessage(
msg.encode('utf-8'),
True
)
if p <> None:
print self.text.messageWebSocketBroadcastError
except:
print self.text.messageWebSocketError
time.sleep(1.0)
def HandleChar(self, ch):
msg = []
tmp = ''
for i in ch:
tmp += i
if len(tmp) == 2:
msg.append(tmp)
tmp = ''
try:
if len(msg) - 1 == int(msg[0], 16) and msg[0] <> 'FF':
if msg[0] == '09' and msg[1] == '40':
self.decode_040(msg)
return
if msg[0] == '08' and msg[1] == '42':
self.decode_042(msg)
return
if msg[0] == '0a' and msg[1] == '4e':
self.decode_04E(msg)
return
if msg[0] == '0a' and msg[1] == '4f':
self.decode_04F(msg)
return
if msg[0] == '08' and msg[1] == '50':
self.decode_050(msg)
return
if msg[0] == '08' and msg[1] == '51':
self.decode_051(msg)
return
if msg[0] == '0a' and msg[1] == '52':
self.decode_052(msg)
return
if msg[0] == '0d' and msg[1] == '54':
self.decode_054(msg)
return
if msg[0] == '0b' and msg[1] == '55':
self.decode_055(msg)
return
if msg[0] == '10' and msg[1] == '56':
self.decode_056(msg)
return
if msg[0] == '09' and msg[1] == '57':
self.decode_057(msg)
return
if msg[0] == '0d' and msg[1] == '58':
self.decode_058(msg)
return
if msg[0] == '0d' and msg[1] == '59':
self.decode_059(msg)
return
if msg[0] == '11' and msg[1] == '5a' and msg[2] == '01':
self.decode_05A_1(msg)
return
if msg[0] == '11' and msg[1] == '5a' and msg[2] == '02':
self.decode_05A_2(msg)
return
if msg[0] == '13' and msg[1] == '5b':
self.decode_05B(msg)
return
if msg[0] == '0f' and msg[1] == '5c':
self.decode_05C(msg)
return
if msg[0] == '15' and msg[1] == '60' and msg[2] == '01':
self.decode_060_01(msg)
return
if msg[0] == '11' and msg[1] == '60' and msg[2] == '02':
self.decode_060_02(msg)
return
if msg[0] == '07' and msg[1] == '70':
self.decode_070(msg)
return
if msg[0] == '0a' and msg[1] == '71':
self.decode_071(msg)
return
if msg[0] == '07' and msg[1] == '10':
self.decode_010(msg)
return
if msg[0] == '0b' and msg[1] == '11':
self.decode_011(msg)
return
if msg[0] == '09' and msg[1] == '13':
self.decode_013(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '00':
self.decode_014_00(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '01':
self.decode_014_01(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '02':
self.decode_014_02(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '04':
self.decode_014_02(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '03':
self.decode_014_03(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '06':
self.decode_014_06(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '07':
self.decode_014_07(msg)
return
if msg[0] == '0a' and msg[1] == '14' and msg[2] == '0d':
self.decode_014_0d(msg)
return
if msg[0] == '0b' and msg[1] == '15':
self.decode_015(msg)
return
if msg[0] == '07' and msg[1] == '16':
self.decode_016(msg)
return
if msg[0] == '07' and msg[1] == '18':
self.decode_018(msg)
return
if msg[0] == '09' and msg[1] == '19' and int(msg[2], 16) == 11:
self.decode_019_B(msg)
return
if msg[0] == '09' and msg[1] == '19' and int(msg[2]) >= 8:
self.decode_019_8(msg)
return
if msg[0] == '09' and msg[1] == '19' and int(msg[2]) >= 6:
self.decode_019_6(msg)
return
if msg[0] == '09' and msg[1] == '19' and int(msg[2]) >= 2:
self.decode_019_2(msg)
return
if msg[0] == '09' and msg[1] == '19' and int(msg[2]) >= 0:
self.decode_019(msg)
return
if msg[0] == '08' and msg[1] == '20':
self.decode_020(msg)
return
if msg[0] == '1c' and msg[1] == '21':
self.decode_021(msg)
return
if msg[0] == '06' and msg[1] == '30' and msg[2] <> '04':
self.decode_030_0(msg)
return
if msg[0] == '06' and msg[1] == '30' and msg[2] == '04':
self.decode_030_1(msg)
return
if msg[0] == '0d' and msg[1] == '01' and msg[2] == '00':
self.decode_00d(msg)
return
if msg[0] == '0d' and msg[1] == '01' and msg[2] == '01':
self.decode_01d(msg)
return
if msg[0] == '0d' and msg[1] == '01' and msg[2] == '02':
self.decode_02d(msg)
return
if msg[0] == '0d' and msg[1] == '01' and msg[2] == '03':
self.decode_03d(msg)
return
if msg[0] == '0d' and msg[1] == '01' and msg[2] == '04':
self.decode_04d(msg)
return
if msg[0] == '0d' and msg[1] == '01' and msg[2] == 'ff':
self.decode_ff(msg)
return
if msg[0] == '14' and msg[1] == '01' and msg[2] == '00':
self.decode_14_00(msg)
return
if msg[0] == '14' and msg[1] == '01' and msg[2] == '01':
self.decode_01d(msg)
return
if msg[0] == '14' and msg[1] == '01' and msg[2] == '02':
self.decode_02d(msg)
return
if msg[0] == '14' and msg[1] == '01' and msg[2] == '03':
self.decode_03d(msg)
return
if msg[0] == '14' and msg[1] == '01' and msg[2] == '04':
self.decode_04d(msg)
return
if msg[0] == '14' and msg[1] == '01' and msg[2] == 'ff':
self.decode_ff(msg)
return
if msg[0] == '14' and msg[1] == '01' and msg[2] == '07':
self.decode_14_07(msg)
return
if msg[1] == '01' and msg[2] == 'FF':
self.decode_000(msg)
return
if msg[0] == '04' and msg[1] == '02':
self.decode_002(msg)
return
if msg[1] == '03':
self.decode_003(msg)
return
if self.bDebug:
eg.PrintError(self.text.messageUKnwn + str(msg))
# self.TriggerEvent(self.text.messageUKnwn + str(msg))
else:
if msg[0] <> 'FF':
eg.PrintError(self.text.messageL + str(msg))
except:
pass
def replaceFunc(self, data):
data = data.strip()
if data == "CR":
return chr(13)
elif data == "LF":
return chr(10)
else:
return None
def hextobin(self, h):
return bin(int(h, 16))[2:].zfill(len(h) * 4)
def WriteMsg(self, data, w_msg, w_key):
# try:
# if self.bDebug:
# print self.text.messageDbg, data
# data = data.replace(' ', '')
# data = eg.ParseString(data, self.replaceFunc)
# data = data.decode('hex')
# self.hold = True
# self.serial.write(str(data))
# eg.Wait(0.01)
# self.hold = False
# if (
# (self.use_websockets or self.use_tornadoWebsockets) and
# w_msg <> '' and
# w_key <> ''
# ):
# self.SavePersistent(w_msg, w_key)
# except:
# self.TriggerEvent(self.text.rfxtrx_lost)
if self.bDebug:
print self.text.messageDbg, data
data = data.replace(' ', '')
data = eg.ParseString(data, self.replaceFunc)
data = data.decode('hex')
self.hold = True
self.serial.write(str(data))
eg.Wait(0.01)
self.hold = False
if (
(self.use_websockets or self.use_tornadoWebsockets) and
w_msg <> '' and
w_key <> ''
):
self.SavePersistent(w_msg, w_key)
def WriteRemoteKey(self, data):
if self.bDebug:
print self.text.messageDbg, data
data = data.replace(' ', '')
data = eg.ParseString(data, self.replaceFunc)
data = data.decode('hex')
self.hold = True
self.serial.write(str(data))
eg.Wait(0.01)
self.hold = False
def LogToFile(self, s):
timeStamp = str(
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
)
logStr = timeStamp + "\t" + s + "<br\n>"
fileHandle = None
progData = eg.configDir + '\plugins\RFXtrx'
if (
not os.path.exists(progData)
and not os.path.isdir(progData)
):
os.makedirs(progData)
fileHandle = open(
progData + '/' +
self.name + '.html', 'a'
)
fileHandle.write(logStr)
fileHandle.close()
def sensorLost(self, myArgument):
eg.TriggerEvent(repr(myArgument))
lc = myArgument.split(':')[3].split(' ')[1]
try:
del self.sensors_status[lc]
except:
pass
try:
self.sensors_status[lc] = myArgument
except:
pass
if self.use_websockets or self.use_tornadoWebsockets:
self.BroadcastMessage(myArgument)
def sensorBack(self, myArgument):
eg.TriggerEvent(repr(myArgument))
bc = myArgument.split(':')[3].split(' ')[1]
try:
del self.sensors_status[bc]
except:
pass
try:
self.sensors_status[bc] = myArgument
except:
pass
if self.use_websockets or self.use_tornadoWebsockets:
self.BroadcastMessage(myArgument)
def eventMonitor(self, monitored, decoded, base, timeout):
try:
eg.scheduler.CancelTask(monitored)
except:
if decoded <> None:
self.sensorBack(
self.text.txt_signal_back + ': ' + base
)
monitored = eg.scheduler.AddTask(
timeout,
self.sensorLost,
self.text.txt_taskObj + ': ' + base
)
return monitored
def eventTrigger(self, decoded, base, pload):
msg = str(base) + ' : ' + str(pload)
try:
if str(decoded)[:-2] <> pload[:-2] or self.bDupEvents:
self.TriggerEvent(str(base), payload=str(pload))
if self.bLogToFile:
self.LogToFile(msg)
if self.use_websockets or self.use_tornadoWebsockets:
self.SavePersistent(msg, str(base))
except:
self.TriggerEvent(str(base), payload=str(pload))
if self.bLogToFile:
self.LogToFile(msg)
def eventTrigger2(self, decoded, base, pload, value, m_key):
msg = str(base) + ' : ' + str(pload)
try:
if str(decoded)[:-2] <> value[:-2] or self.bDupEvents:
self.TriggerEvent(str(base), payload=str(pload))
if self.bLogToFile:
self.LogToFile(msg)
if self.use_websockets or self.use_tornadoWebsockets:
self.SavePersistent(msg, m_key)
except:
self.TriggerEvent(str(base), payload=str(pload))
if self.bLogToFile:
self.LogToFile(msg)
def eventTrigger3(self, decoded, base, pload, value, m_key):
msg = str(base) + ' : ' + str(pload)
try:
if decoded <> value or self.bDupEvents:
self.TriggerEvent(str(base), payload=str(pload))
if self.bLogToFile:
self.LogToFile(msg)
if self.use_websockets or self.use_tornadoWebsockets:
self.SavePersistent(msg, m_key)
except:
self.TriggerEvent(str(base), payload=str(pload))
if self.bLogToFile:
self.LogToFile(msg)
def eventRemote(self, base, pload):
self.TriggerEvent(str(base), payload=str(pload))
def GetMacroIndex(self, label, name, my_macro_indx):
if not self.mMacroNames:
return None
if my_macro_indx == None:
try:
for index, m_name in enumerate(
eg.document.__dict__['root'].childs
):
if (
m_name.name.find('<') <> -1
and
m_name.name.find('>') <> -1
):
my_macro_indx = index
break
except:
pass
try:
for index, m_name in enumerate(
eg.document.__dict__['root'].childs
):
if m_name.name == 'RFXtrx: ' + label + ': ' + name:
my_macro_indx = index
break
except:
return my_macro_indx
else:
for index, m_name in enumerate(
eg.document.__dict__['root'].childs
):
if m_name.name == 'RFXtrx: ' + label + ': ' + name:
my_macro_indx = index
return my_macro_indx
def SetMacroName(self, label, name, macro_indx):
if macro_indx <> None and self.mMacroNames:
new_name = (
'RFXtrx: '
+ label
+ ': '
+ name
)
eg.document.__dict__['root'].childs[macro_indx].name = new_name
eg.document.__dict__['root'].childs[macro_indx].Refresh()
def decode_000(self, msg):
if msg[2] == 'FF':
eg.PrintError(self.text.messageT + str(msg[4]))
def decode_14_00(self, msg):
if not self.deviceCheck and self.init:
self.init = False
self.interfaceMode = msg
print 'Interface mode: ', msg
receiver_transceiver_types = {
'50': '310MHz',
'51': '315MHz',
'52': '433.92MHz receiver only',
'53': '433.92MHz transceiver',
'55': '868.00MHz',
'56': '868.00MHz FSK',
'57': '868.30MHz',
'58': '868.30MHz FSK',
'59': '868.35MHz',
'5A': '868.35MHz FSK',
'5B': '868.95MHz'
}
receiver_transceiver_fw = {
'00': 'Type1 RFXrec receive only firmware',
'01': 'Type1',
'02': 'Type2',
'03': 'Ext',
'04': 'Ext2'
}
try:
print(self.text.rfxtrx + str(receiver_transceiver_types[msg[5]]))
self.fwVer = int(msg[6], 16) + 1000
print self.text.fwVersion + str(self.fwVer)
fwType = receiver_transceiver_fw[msg[14]]
print self.text.rfxtrx_fw + fwType
except:
eg.PrintError(self.text.decodeError + str(msg))
else:
self.deviceCheck = False
if msg[0] == '14' and msg[1] == '01':
pass
else:
self.TriggerEvent(self.text.rfxtrx_lost)
def decode_00d(self, msg):
if not self.deviceCheck and self.init:
self.init = False
self.interfaceMode = msg
print 'Interface mode: ', msg
receiver_transceiver_types = {
'50': '310MHz',
'51': '315MHz',
'52': '433.92MHz receiver only',
'53': '433.92MHz transceiver',
'55': '868.00MHz',
'56': '868.00MHz FSK',
'57': '868.30MHz',
'58': '868.30MHz FSK',
'59': '868.35MHz',
'5A': '868.35MHz FSK',
'5B': '868.95MHz'
}
try:
print(self.text.fwVersion + str(int(msg[6], 16)))
self.fwVer = int(msg[6], 16)
print(self.text.rfxtrx + str(receiver_transceiver_types[msg[5]]))
if self.fwVer < 163:
print self.text.rfxtrx_type + "1"
if self.fwVer >= 163 and self.fwVer < 225:
print self.text.rfxtrx_type + "2"
if self.fwVer >= 225:
print self.text.rfxtrx_type + "433E"
except:
eg.PrintError(self.text.decodeError + str(msg))
else:
self.deviceCheck = False
ml = len(msg) - 1
if hex(ml).replace('x', '') == msg[0]:
pass
else:
self.TriggerEvent(self.text.rfxtrx_lost)
def decode_01d(self, msg):
eg.PrintError(self.text.unknown_RFY_remote)
def decode_02d(self, msg):
eg.PrintError(self.text.no_extended_hardware_present)
def decode_ff(self, msg):
eg.PrintNotice("RFXtrx: Please, flash the latest firmware")
def decode_14_07(self, msg):
def cprMsg(msg):
cpr = ''
validRFXCOM = False
try:
for i in range(5, len(msg)):
cpr += chr(int((msg[i]), 16))
print cpr + '.', self.text.rfxtrx_started
if cpr == "Copyright RFXCOM":
validRFXCOM = True
except:
validRFXCOM = False
return validRFXCOM
validRFXCOM = False
validRFXCOM = cprMsg(msg)
if not validRFXCOM:
eg.PrintNotice(
"RFXtrx: Genuin RFXtrx device verification failed!"
)
# self.__stop__()
def decode_03d(self, msg):
log = (
'RFY remote location: ' + str(int(msg[5], 16)) +
' ID1: ' + str(msg[6]) +
' ID2: ' + str(msg[7]) +
' ID3: ' + str(msg[8]) +
' Unit number: ' + str(msg[9])
)
if (
str(msg[6]) == '00' and
str(msg[7]) == '00' and
str(msg[8]) == '00' and
str(msg[9]) == '00'
):
log = (
'RFY remote location: ' + str(int(msg[5], 16)) +
' is empty '
)
print log
def decode_04d(self, msg):
log = (
'ASA remote location: ' + str(int(msg[5], 16)) +
' ID1: ' + str(msg[6]) +
' ID2: ' + str(msg[7]) +
' ID3: ' + str(msg[8]) +
' Unit number: ' + str(msg[9])
)
if (
str(msg[6]) == '00' and
str(msg[7]) == '00' and
str(msg[8]) == '00' and
str(msg[9]) == '00'
):
log = (
'ASA remote location: ' + str(int(msg[5], 16)) +
' is empty '
)
print log
def decode_002(self, msg):
if msg[0] == '04' and msg[1] == '02':
if msg[2] == '00' or msg[2] == '01':
pass # message sent ok
if msg[2] == '02' or msg[2] == '03':
eg.PrintError('NACK: ' + str(msg))
def decode_003(self, msg):
subtypes = {
'00': 'ac',
'01': 'arc',
'02': 'ati',
'03': 'hideki/upm',
'04': 'lacrosse/viking',
'05': 'ad',
'06': 'mertik',
'07': 'oregon1',
'08': 'oregon2',
'09': 'oregon3',
'0a': 'proguard',
'0b': 'visonic',
'0c': 'nec',
'0d': 'fs20',
'0e': 'reserved',
'0f': 'blinds',
'10': 'rubicson',
'11': 'ae',
'12': 'fineoffset',
'13': 'rgb',
'14': 'rfy',
'15': 'selectplus'
}
try:
print 'Undecoded: ', msg, subtypes[str(msg[2])]
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_040(self, msg):
types = {
'00': 'Digimax, TLX7506',
'01': 'Digimax with short format (no set point)'
}
try:
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
st = int(bin(int(msg[8], 16))[2:].zfill(8)[6:], 2)
md = int(bin(int(msg[8], 16))[2:].zfill(8)[0], 2)
if st == 0:
my_status = 'no status available'
if st == 1:
my_status = 'demand'
if st == 2:
my_status = 'no demand'
if st == 3:
my_status = 'initializing'
if md == 0:
my_mode = 'heating'
if md == 1:
my_mode = 'cooling'
if msg[2] == '00':
pload_msg = (
' temperature: ' +
str(float(int(msg[6], 16))) +
' setpoint: ' +
str(float(int(msg[7], 16))) +
' status: ' +
my_status +
' mode: ' +
my_mode +
' signal: ' + str(int(msg[9][0], 16))
)
elif msg[2] == '01':
pload_msg = (
' temperature: ' +
'0.0' +
' signal: ' + str(int(msg[9][0], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decoder_mems['040'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['040'][base_msg]
except:
pass
self.monitor_mems['040'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['040'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_042(self, msg):
types = {
'00': 'Mertik G6R-H4T1',
'01': 'Mertik G6R-H4TB/G6-H4T/G6R-H4T21-Z22',
'02': 'Mertik G6R-H4TD'
}
try:
# Get the unit ID
dev_id = str(int(msg[4] + msg[5] + msg[6], 16))
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
cmd = int(msg[7][1], 16)
if cmd == 0:
my_cmd = 'off'
elif cmd == 1:
my_cmd = 'on'
elif cmd == 2:
my_cmd = 'up'
elif cmd == 3:
my_cmd = 'down'
elif cmd == 4:
if int(msg[2]) == 0: # G6R-H4T1
my_cmd = 'Run Up'
elif int(msg[2]) == 1: # G6R-H4TB
my_cmd = '2nd Off'
elif cmd == 5:
if int(msg[2]) == 0: # G6R-H4T1
my_cmd = 'Run Down'
elif int(msg[2]) == 1: # G6R-H4TB
my_cmd = '2nd On'
elif cmd == 6:
if int(msg[2]) == 0: # G6R-H4T1
my_cmd = 'Stop'
elif int(msg[2]) == 1: # G6R-H4TB
my_cmd = 'NA'
pload_msg = (
' command: ' +
my_cmd +
' signal: ' + str(int(msg[8][0], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['042'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['042'][base_msg]
except:
pass
self.monitor_mems['042'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['042'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_04E(self, msg):
types = {
'01': 'Maverick ET-732 BBQ temperature sensors'
}
try:
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' temperature Food: ' +
str(float(int(msg[6], 16) * 256 + int(msg[7], 16))) +
' temperature BBQ: ' +
str(float(int(msg[8], 16) * 256 + int(msg[9], 16))) +
' signal: ' + str(int(msg[10][0], 16)) +
' battery: ' + str(int(msg[10][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_04E_mem[base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_04E_mem[base_msg]
except:
pass
self.monitor_04E_mem[base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_04E_mem[base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_04F(self, msg):
types = {
'01': 'Alecto WS1200'
}
signs = {
'0': '+',
'1': '-'
}
try:
# Get the correct sign
sign_bt = bin(int(msg[6], 16))[2:].zfill(8)
sign = signs[sign_bt[0]]
# Calculate the actual temperature
if sign == '+':
tempC = str(
float(
(
int(msg[6], 16) * 256 +
int(msg[7], 16)) / 10.0
)
)
if sign == '-':
tempC = str(
float(
(
(
int(msg[6], 16) & int('7F', 16)) * 256 +
int(msg[7], 16)) / 10.0
)
)
rainTot = str(
float(
(
int(msg[8], 16) * 256 +
int(msg[9], 16)) / 10.0
)
)
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
# Get the channel value
# print msg[4]
if int(dev_id) <> 0:
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' temperature: ' + sign + tempC + ' deg C' +
' rain total: ' + rainTot + ' mm' +
' signal: ' + str(int(msg[10][0], 16)) +
' battery: ' + str(int(msg[10][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_04F_mem[base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_04F_mem[base_msg]
except:
pass
self.monitor_04F_mem[base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_04F_mem[base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_050(self, msg):
types = {
'01': 'THR128/138, THC138',
'02': 'THC238/268,THN132,THWR288,THRN122,THN122,AW129/131',
'03': 'THWR800',
'04': 'RTHN318',
'05': 'La Crosse TX3, TX4, TX17',
'06': 'TS15C,UPM temp only',
'07': 'Viking 02811',
'08': 'La Crosse WS2300',
'09': 'RUBiCSON',
'0a': 'TFA 30.3133',
'0b': 'WT0122'
}
signs = {
'0': '+',
'1': '-'
}
try:
# Get the correct sign
sign_bt = bin(int(msg[6], 16))[2:].zfill(8)
sign = signs[sign_bt[0]]
# Calculate the actual temperature
if sign == '+':
tempC = str(
float(
(
int(msg[6], 16) * 256 +
int(msg[7], 16)) / 10.0
)
)
if sign == '-':
tempC = str(
float(
(
(
int(msg[6], 16) & int('7F', 16)) * 256 +
int(msg[7], 16)) / 10.0
)
)
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
# Get the channel value
# print msg[4]
if int(dev_id) <> 0:
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' temperature: ' + sign + tempC + ' deg C' +
' signal: ' + str(int(msg[8][0], 16)) +
' battery: ' + str(int(msg[8][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['050'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['050'][base_msg]
except:
pass
self.monitor_mems['050'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['050'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_051(self, msg):
types = {
'01': 'La Crosse TX3',
'02': 'La Crosse WS2300',
'03': 'Inovalley S80 plant humidity sensor'
}
if self.fwVer < 54:
statuses = {
'00': 'dry',
'01': 'comfort',
'02': 'normal',
'03': 'wet'
}
else:
statuses = {
'00': 'normal',
'01': 'comfort',
'02': 'dry',
'03': 'wet'
}
try:
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
# Get the channel value
# print msg[4]
if int(dev_id) <> 0:
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' humidity: ' + str(int(msg[6], 16)) + ' %RH' +
' status: ' + statuses[msg[7]] +
' signal: ' + str(int(msg[8][0], 16)) +
' battery: ' + str(int(msg[8][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['051'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['051'][base_msg]
except:
pass
self.monitor_mems['051'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['051'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_052(self, msg):
types = {
'01': 'THGN122/123, THGN132, THGR122/228/238/268',
'02': 'THGR810, THGN800',
'03': 'RTGR328',
'04': 'THGR328',
'05': 'WTGR800',
'06': 'THGR918, THGRN228, THGN500',
'07': 'TFA TS34C, Cresta',
'08': 'WT260, WT260H, WT440H, WT450, WT450H',
'09': 'Viking 02035,02038',
'0a': 'Rubicson',
'0b': 'Oregon EW109',
'0c': 'Imagintronix Soil sensor',
'0d': 'Alecto WS1700 and compatibles',
'0e': 'Alecto WS4500 and compatibles'
}
signs = {
'0': '+',
'1': '-'
}
if self.fwVer < 54:
statuses = {
'00': 'dry',
'01': 'comfort',
'02': 'normal',
'03': 'wet'
}
else:
statuses = {
'00': 'normal',
'01': 'comfort',
'02': 'dry',
'03': 'wet'
}
try:
# Get the correct sign
sign_bt = bin(int(msg[6], 16))[2:].zfill(8)
sign = signs[sign_bt[0]]
# Calculate the actual temperature
if sign == '+':
tempC = str(
float(
(
int(msg[6], 16) * 256 +
int(msg[7], 16)) / 10.0
)
)
if sign == '-':
tempC = str(
float(
(
(
int(msg[6], 16) & int('7F', 16)) * 256 +
int(msg[7], 16)) / 10.0
)
)
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
# Get the channel value
# print msg[4]
if int(dev_id) <> 0:
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' temperature: ' + sign + tempC + ' deg C' +
' humidity: ' + str(int(msg[8], 16)) + ' %RH' +
' status: ' + statuses[msg[9]] +
' signal: ' + str(int(msg[10][0], 16)) +
' battery: ' + str(int(msg[10][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['052'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['052'][base_msg]
except:
pass
self.monitor_mems['052'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['052'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_054(self, msg):
types = {
'01': 'BTHR918, BTHGN129',
'02': 'BTHR918N, BTHR968'
}
signs = {
'0': '+',
'1': '-'
}
if self.fwVer < 54:
statuses = {
'00': 'dry',
'01': 'comfort',
'02': 'normal',
'03': 'wet'
}
else:
statuses = {
'00': 'normal',
'01': 'comfort',
'02': 'dry',
'03': 'wet'
}
forecasts = {
'00': 'no forecast available',
'01': 'sunny',
'02': 'partly cloudy',
'03': 'cloudy',
'04': 'rain'
}
try:
# Get the correct sign
sign_bt = bin(int(msg[6], 16))[2:].zfill(8)
sign = signs[sign_bt[0]]
# Calculate the actual temperature
if sign == '+':
tempC = str(
float(
(
int(msg[6], 16) * 256 +
int(msg[7], 16)) / 10.0
)
)
if sign == '-':
tempC = str(
float(
(
(
int(msg[6], 16) & int('7F', 16)) * 256 +
int(msg[7], 16)) / 10.0
)
)
# Calculate the barometer value
barometer = str(
float(
(
int(msg[10], 16) * 256 +
int(msg[11], 16)
)
)
)
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
if int(dev_id) <> 0:
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' temperature: ' + sign + tempC + ' deg C' +
' humidity: ' + str(int(msg[8], 16)) + ' %RH' +
' status: ' + statuses[msg[9]] +
' baro: ' + barometer + ' hPa' +
' forecast: ' + forecasts[msg[12]] +
' signal: ' + str(int(msg[13][0], 16)) +
' battery: ' + str(int(msg[13][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['054'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['054'][base_msg]
except:
pass
self.monitor_mems['054'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['054'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_055(self, msg):
types = {
'01': 'RGR126/682/918',
'02': 'PCR800',
'03': 'TFA',
'04': 'UPM RG700',
'05': 'La Crosse WS2300',
'06': 'La Crosse TX5',
'07': 'Alecto WS4500 and compatibles'
}
battery_statuses = {
'0': '10%',
'1': '20%',
'2': '30%',
'3': '40%',
'4': '50%',
'5': '60%',
'6': '70%',
'7': '80%',
'8': '90%',
'9': '100%'
}
try:
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
# Get the battery status
batt_level = battery_statuses[msg[11][1]]
if int(dev_id) <> 0:
if msg[2] == '01':
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' rainrate: ' + str(int(msg[6], 16) * 256 +
int(msg[7], 16)) + ' mm/hr' +
' rainTotal: ' + str((int(msg[8], 16) * 65535 +
int(msg[9], 16) * 256 +
int(msg[10], 16)) / 10) + ' mm' +
' signal: ' + str(int(msg[11][0], 16)) +
' battery: ' + batt_level
)
if msg[2] == '02':
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' rainrate: ' + str((int(msg[6], 16) * 256 +
int(msg[7], 16)) / 100) + ' mm/hr' +
' rainTotal: ' + str((int(msg[8], 16) * 65535 +
int(msg[9], 16) * 256 +
int(msg[10], 16)) / 10) + ' mm' +
' signal: ' + str(int(msg[11][0], 16)) +
' battery: ' + batt_level
)
if (
msg[2] == '03' or
msg[2] == '04' or
msg[2] == '05' or
msg[2] == '07'
):
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' rainTotal: ' + str((int(msg[8], 16) * 65535 +
int(msg[9], 16) * 256 +
int(msg[10], 16)) / 10) + ' mm' +
' signal: ' + str(int(msg[11][0], 16)) +
' battery: ' + batt_level
)
if (
msg[2] == '06'
):
flCount = int(msg[10], 16)
try:
res = self.flipCount[dev_id]
except:
# Happens at restart
try:
tst = self.totalRain[dev_id]
except:
self.totalRain[dev_id] = 0.001
if flCount > 0:
self.flipCount[dev_id] = flCount - 1
else:
self.flipCount[dev_id] = 15
# Use next if counting on first event
self.flCount_prev[dev_id] = self.flipCount[dev_id]
# Use next if not counting on first event
# self.flCount_prev[dev_id] = flCount
if flCount <> self.flCount_prev[dev_id]:
if self.flipCount[dev_id] > flCount:
self.flipCount[dev_id] = (
flCount + 16 - self.flipCount[dev_id]
)
addRain = float(
(self.flipCount[dev_id] - flCount) * 0.266
)
else:
addRain = float(
(flCount - self.flipCount[dev_id]) * 0.266
)
self.flipCount[dev_id] = flCount
self.totalRain[dev_id] += addRain
CurrentStateData.totalRain[dev_id] = (
self.totalRain[dev_id]
)
self.flCount_prev[dev_id] = flCount
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' rainTotal: ' +
str("%.2f" % self.totalRain[dev_id]) +
' mm' +
' signal: ' + str(int(msg[11][0], 16)) +
' battery: ' + batt_level
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['055'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['055'][base_msg]
except:
pass
self.monitor_mems['055'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['055'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_056(self, msg):
types = {
'01': 'WTGR800',
'02': 'WGR800',
'03': 'STR918, WGR918',
'04': 'TFA',
'05': 'UPM WDS500',
'06': 'La Crosse WS2300',
'07': 'Alecto WS4500 and compatibles'
}
signs = {
'0': '+',
'1': '-'
}
battery_statuses = {
'0': '10%',
'1': '20%',
'2': '30%',
'3': '40%',
'4': '50%',
'5': '60%',
'6': '70%',
'7': '80%',
'8': '90%',
'9': '100%'
}
try:
# Get the unit ID
dev_id = str(int(msg[4] + msg[5], 16))
# Get the channel value
# print msg[4]
if int(dev_id) <> 0:
wind_dir = float(int(msg[6], 16) * 256 + int(msg[7], 16))
strDirection = "---"
if wind_dir > 348.75 or wind_dir < 11.26:
strDirection = "N"
elif wind_dir < 33.76:
strDirection = "NNE"
elif wind_dir < 56.26:
strDirection = "NE"
elif wind_dir < 78.76:
strDirection = "ENE"
elif wind_dir < 101.26:
strDirection = "E"
elif wind_dir < 123.76:
strDirection = "ESE"
elif wind_dir < 146.26:
strDirection = "SE"
elif wind_dir < 168.76:
strDirection = "SSE"
elif wind_dir < 191.26:
strDirection = "S"
elif wind_dir < 213.76:
strDirection = "SSW"
elif wind_dir < 236.26:
strDirection = "SW"
elif wind_dir < 258.76:
strDirection = "WSW"
elif wind_dir < 281.26:
strDirection = "W"
elif wind_dir < 303.76:
strDirection = "WNW"
elif wind_dir < 326.26:
strDirection = "NW"
elif wind_dir < 348.76:
strDirection = "NNW"
if msg[2] == '04':
# Get the correct sign
sign_bt = bin(int(msg[12], 16))[2:].zfill(8)
sign = signs[sign_bt[0]]
# Calculate the actual temperature
if sign == '+':
tempC = str(
float(
(
int(msg[12], 16) * 256 +
int(msg[13], 16)) / 10.0
)
)
if sign == '-':
tempC = str(
float(
(
(
int(msg[12], 16) & int('7F', 16)) * 256 +
int(msg[13], 16)) / 10.0
)
)
# Get the correct chill sign
chill_sign_bt = bin(int(msg[14], 16))[2:].zfill(8)
chill_sign = signs[chill_sign_bt[0]]
# Calculate the actual chill
if chill_sign == '+':
chillC = str(
float(
(
int(msg[14], 16) * 256 +
int(msg[15], 16)) / 10.0
)
)
if chill_sign == '-':
chillC = str(
float(
(
(
int(msg[14], 16) & int('7F', 16)) * 256 +
int(msg[15], 16)) / 10.0
)
)
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' direction: ' + strDirection +
' average speed: ' + str(float(int(msg[8], 16) * 256 +
int(msg[9], 16)) / 10.0) + ' m/s' +
' gust: ' + str(float(int(msg[10], 16) * 256 +
int(msg[11], 16)) / 10.0) + ' m/s' +
' temperature: ' + temp_sign + tempC + ' deg C' +
' chill: ' + chill_sign + chillC + ' deg C' +
' signal: ' + str(int(msg[16][0], 16)) +
' battery: ' + battery_statuses[msg[16][1]]
)
if msg[2] == '05':
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' direction: ' + strDirection +
' gust: ' + str(float(int(msg[10], 16) * 256 +
int(msg[11], 16)) / 10.0) + ' m/s' +
' signal: ' + str(int(msg[16][0], 16)) +
' battery: ' + battery_statuses[msg[16][1]]
)
if (
msg[2] == '01' or
msg[2] == '02' or
msg[2] == '03' or
msg[2] == '06' or
msg[2] == '07'
):
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' direction: ' + strDirection +
' average speed: ' + str(float(int(msg[8], 16) * 256 +
int(msg[9], 16)) / 10.0) + ' m/s' +
' gust: ' + str(float(int(msg[10], 16) * 256 +
int(msg[11], 16)) / 10.0) + ' m/s' +
' signal: ' + str(int(msg[16][0], 16)) +
' battery: ' + battery_statuses[msg[16][1]]
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['056'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['056'][base_msg]
except:
pass
self.monitor_mems['056'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['056'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_057(self, msg):
types = {
'01': 'UVN128, UV138',
'02': 'UVN800',
'03': 'TFA'
}
signs = {
'0': '+',
'1': '-'
}
try:
uv_level = int(msg[6], 16) / 10
uv_risk = "----"
if uv_level < 3:
uv_risk = "Low"
elif uv_level < 6:
uv_risk = "Medium"
elif uv_level < 8:
uv_risk = "High"
elif uv_level < 11:
uv_risk = "Very High"
else:
uv_risk = "Dangerous"
if msg[2] == '01' or msg[2] == '02':
# Get the unit ID
dev_id = str(int(msg[4], 16) * 256 + int(msg[5], 16))
if int(dev_id) <> 0:
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' UV level: ' + str(uv_level) +
' status: ' + uv_risk +
' signal: ' + str(int(msg[9][0], 16)) +
' battery: ' + str(int(msg[9][1], 16))
)
if msg[2] == '03':
# Get the correct sign
sign_bt = bin(int(msg[7], 16))[2:].zfill(8)
sign = signs[sign_bt[0]]
# Calculate the actual temperature
if sign == '+':
tempC = str(
float(
(
int(msg[7], 16) * 256 +
int(msg[8], 16)) / 10.0
)
)
if sign == '-':
tempC = str(
float(
(
(
int(msg[7], 16) & int('7F', 16)) * 256 +
int(msg[8], 16)) / 10.0
)
)
# Get the unit ID
dev_id = str(int(msg[4], 16) * 256 + int(msg[5], 16))
if int(dev_id) <> 0:
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' temperature: ' + sign + tempC + ' deg C' +
' UV level: ' + str(uv_level) +
' status: ' + uv_risk +
' signal: ' + str(int(msg[9][0], 16)) +
' battery: ' + str(int(msg[9][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['057'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['057'][base_msg]
except:
pass
self.monitor_mems['057'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['057'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_058(self, msg):
def checkStrLength(st):
if len(st) < 2:
st = "0" + st
return st
dayOfweek = {
'1': 'Sunday',
'2': 'Monday',
'3': 'Tuesday',
'4': 'Wednesday',
'5': 'Thursday',
'6': 'Friday',
'7': 'Saturday'
}
types = {
'01': 'DT1 - RTGR328N'
}
try:
# Get the unit ID
dev_id = str(int(msg[4], 16) * 256 + int(msg[5], 16))
# year
year = checkStrLength(str(int(msg[6], 16)))
# month
month = checkStrLength(str(int(msg[7], 16)))
# day
day = checkStrLength(str(int(msg[8], 16)))
# dayOfweek
dOfweek = dayOfweek[str(int(msg[9], 16))]
# hours
hours = checkStrLength(str(int(msg[10], 16)))
# minutes
minutes = checkStrLength(str(int(msg[11], 16)))
# seconds
seconds = checkStrLength(str(int(msg[12], 16)))
if int(dev_id) <> 0:
# print msg
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' Date (yy/mm/dd): ' + year + '/' + month + '/' + day +
' Day of week: ' + dOfweek +
' Time (hh:mm:ss) : ' + hours + ':' + minutes + ':' + seconds +
' signal: ' + str(int(msg[13][0], 16)) +
' battery: ' + str(int(msg[13][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['058'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['058'][base_msg]
except:
pass
self.monitor_mems['058'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['058'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_059(self, msg):
types = {
'01': 'CM113'
}
try:
# Get the unit ID
dev_id = str(int(msg[4], 16) * 256 + int(msg[5], 16))
# Counter
counter = str(int(msg[6], 16))
# Channel 1
channel_1 = float((int(msg[7], 16) * 256 + int(msg[8], 16))) / 10.0
channel_1 = str("%.2f" % channel_1)
# Channel 2
channel_2 = float((int(msg[9], 16) * 256 + int(msg[10], 16))) / 10.0
channel_2 = str("%.2f" % channel_2)
# Channel 3
channel_3 = float((int(msg[11], 16) * 256 + int(msg[12], 16))) / 10.0
channel_3 = str("%.2f" % channel_3)
if int(dev_id) <> 0:
# print msg
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' Counter: ' + counter +
' Channel 1: ' + channel_1 + ' A' +
' Channel 2: ' + channel_2 + ' A' +
' Channel 3: ' + channel_3 + ' A' +
' signal: ' + str(int(msg[13][0], 16)) +
' battery: ' + str(int(msg[13][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['059'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['059'][base_msg]
except:
pass
self.monitor_mems['059'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['059'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_060_01(self, msg):
types = {
'01': 'CARTELECTRONIC TIC'
}
try:
# Get the unit ID
dev_id = msg[4] + msg[5] + msg[6] + msg[7] + msg[8]
# Contract type
contract = msg[9]
# Counter 1
counter_1 = str(
(int(msg[10], 16) << 24) +
(int(msg[11], 16) << 16) +
(int(msg[12], 16) << 8) +
(int(msg[13], 16))
)
# Counter 2
counter_2 = str(
(int(msg[14], 16) << 24) +
(int(msg[15], 16) << 16) +
(int(msg[16], 16) << 8) +
(int(msg[17], 16))
)
# State
state = str(self.hextobin(msg[20]))
power = '0'
teleinfo = 'Present'
pejp = ''
if int(state[5]) == 1:
teleinfo = 'Not present'
if int(state[6]) == 1:
power = float((int(msg[18], 16) * 256 + int(msg[19], 16)))
power = str("%.2f" % power)
if state[3] + state[4] == '00':
pejp = 'No change price time warning'
if state[3] + state[4] == '01':
pejp = 'White'
if state[3] + state[4] == '10':
pejp = 'Blue'
if state[3] + state[4] == '11':
pejp = 'Red / PEJP'
if dev_id <> '':
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
'Contract/Price: ' + contract +
' Counter1: ' + counter_1 +
' Counter2: ' + counter_2 +
' Teleinfo: ' + teleinfo +
' PEJP or DEMAIN: ' + pejp +
' Apparent power: ' + str(power) +
' signal: ' + str(int(msg[21][0], 16)) +
' battery: ' + str(int(msg[21][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['060_01'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['060_01'][base_msg]
except:
pass
self.monitor_mems['060_01'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['060_01'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_060_02(self, msg):
types = {
'02': 'CARTELECTRONIC ENCODER'
}
try:
# Get the unit ID
dev_id = msg[4] + msg[5] + msg[6] + msg[7]
# Counter 1
counter_1 = str(
(int(msg[8], 16) << 24) +
(int(msg[9], 16) << 16) +
(int(msg[10], 16) << 8) +
(int(msg[11], 16))
)
# Counter 2
counter_2 = str(
(int(msg[12], 16) << 24) +
(int(msg[13], 16) << 16) +
(int(msg[14], 16) << 8) +
(int(msg[15], 16))
)
if dev_id <> '':
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
'Counter1: ' + counter_1 +
' Counter2: ' + counter_2 +
' signal: ' + str(int(msg[17][0], 16)) +
' battery: ' + str(int(msg[17][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_mems['060_02'][base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_mems['060_02'][base_msg]
except:
pass
self.monitor_mems['060_02'][base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_mems['060_02'][base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_05A_1(self, msg):
types = {
'01': 'CM119/160'
}
try:
# Get the unit ID
dev_id = str(int(msg[4], 16) * 256 + int(msg[5], 16))
# Counter
counter = str(int(msg[6], 16))
# Instant power consumption in Watts
instant = str("%.2f" %
float(
eval('0x' + msg[7]) * 0x1000000 +
eval('0x' + msg[8]) * 0x10000 +
eval('0x' + msg[9]) * 0x100 +
eval('0x' + msg[10])
)
)
# Total energy usage in Wh
f_usage = float(
eval('0x' + msg[11]) * 0x10000000000 +
eval('0x' + msg[12]) * 0x100000000 +
eval('0x' + msg[13]) * 0x1000000 +
eval('0x' + msg[14]) * 0x10000 +
eval('0x' + msg[15]) * 0x100 +
eval('0x' + msg[16])
) / 223.666
usage = str("%.2f" % f_usage)
if int(dev_id) <> 0:
# print msg
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' Counter: ' + counter +
' Instant power usage: ' + instant + ' W' +
' Total energy usage: ' + usage + ' Wh' +
' signal: ' + str(int(msg[17][0], 16)) +
' battery: ' + str(int(msg[17][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_05A_1_mem[base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_05A_1_mem[base_msg]
except:
pass
self.monitor_05A_1_mem[base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_05A_1_mem[base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_05A_2(self, msg):
types = {
'02': 'CM180'
}
try:
# Get the unit ID
dev_id = str(int(msg[4], 16) * 256 + int(msg[5], 16))
# Counter
counter = str(int(msg[6], 16))
# Instant power consumption in Watts
instant = str("%.2f" %
float(
eval('0x' + msg[7]) * 0x1000000 +
eval('0x' + msg[8]) * 0x10000 +
eval('0x' + msg[9]) * 0x100 +
eval('0x' + msg[10])
)
)
if int(counter) == 0:
# Total energy usage in Wh
f_usage = float(
eval('0x' + msg[11]) * 0x10000000000 +
eval('0x' + msg[12]) * 0x100000000 +
eval('0x' + msg[13]) * 0x1000000 +
eval('0x' + msg[14]) * 0x10000 +
eval('0x' + msg[15]) * 0x100 +
eval('0x' + msg[16])
) / 223.666
self.usage_05A_2 = str("%.2f" % f_usage)
if int(dev_id) <> 0:
# print msg
base_msg = (
'Type: ' + types[msg[2]] +
' id: ' + dev_id
)
pload_msg = (
' Counter: ' + counter +
' Instant power usage: ' + instant + ' W' +
' Total energy usage: ' + self.usage_05A_2 + ' Wh' +
' signal: ' + str(int(msg[17][0], 16)) +
' battery: ' + str(int(msg[17][1], 16))
)
decode_param = None
mon_param = None
try:
decode_param = self.decode_05A_2_mem[base_msg]
except:
pass
self.eventTrigger(
decode_param,
base_msg,
pload_msg
)
try:
mon_param = self.monitor_05A_2_mem[base_msg]
except:
pass
self.monitor_05A_2_mem[base_msg] = self.eventMonitor(
mon_param,
decode_param,
base_msg,
self.sensorLostTimeOut
)
self.decode_05A_2_mem[base_msg] = pload_msg
except:
eg.PrintError(self.text.decodeError + str(msg))
def decode_05B(self, msg):
types = {
'01': 'CM180i'
}
try:
# Get the unit ID
dev_id = str(int(msg[4], 16) * 256 + int(msg[5], 16))
# Counter
counter = str(int(msg[6], 16))
# Instant current consumption in ampere
ampere_1 = str("%.2f" %
float(int(msg[7], 16) * 256 + int(msg[8], 16)) / 10.0
)
ampere_2 = str("%.2f" %
float(int(msg[9], 16) * 256 + int(msg[10], 16)) / 10.0
)
ampere_3 = str("%.2f" %
float(int(msg[11], 16) * 256 + int(msg[12], 16)) / 10.0
)
# Total energy usage in Wh
usage = '0'
f_usage = float(
eval('0x' + msg[13]) * 0x10000000000 +
eval('0x' + msg[14]) * 0x100000000 +
eval('0x' + msg[15]) * 0x1000000 +
eval('0x' + msg[16]) * 0x10000 +
eval('0x' + msg[17]) * 0x100 +
eval('0x' + msg[18])
) / 223.666
if int(msg[6], 16) == 0:
usage = str("%.2f" % f_usage)
if int(dev_id) <> 0:
# print msg
base_msg = (
'Type: ' + types[msg[2]] +