|
From: <ni...@us...> - 2010-11-04 13:28:04
|
Revision: 72
http://openautomation.svn.sourceforge.net/openautomation/?rev=72&view=rev
Author: nilss1
Date: 2010-11-04 13:27:57 +0000 (Thu, 04 Nov 2010)
Log Message:
-----------
encoding of DPT and send to KNX
Modified Paths:
--------------
PyWireGate/trunk/knx_connector/DPT_Types.py
PyWireGate/trunk/knx_connector/KNX_Connector.py
Modified: PyWireGate/trunk/knx_connector/DPT_Types.py
===================================================================
--- PyWireGate/trunk/knx_connector/DPT_Types.py 2010-11-04 10:54:37 UTC (rev 71)
+++ PyWireGate/trunk/knx_connector/DPT_Types.py 2010-11-04 13:27:57 UTC (rev 72)
@@ -20,6 +20,8 @@
### Da die EIBConnection Lib den string nicht hexadezimal zurueckgibt,
### sondern als LIST mit den dezimalen Werten ist das decode hier ein bischen angepasst
+import struct
+
class dpt_type:
def __init__(self,WireGateInstance):
self.WG = WireGateInstance
@@ -43,6 +45,26 @@
14:self.decodeDPT14, # EIS 9 / 4 byte float
16:self.decodeDPT16 # EIS 15 / 14 byte Text
}
+ self.ENCODER = {
+ 1:self.encodeDPT1, # EIS 1/7 / 1 bit 0=Aus/1=Ein
+ 2:self.encodeDPT2, # EIS 8 / 2 bit 0,1=Frei/2=Prio_Aus/3=Prio_Ein
+ 3:self.encodeDPT3, # EIS 2 / 4 bit
+ 4:self.encodeDPT4, # EIS 13 / 1 byte 1 Zeichen
+ 5:self.encodeDPT5, # EIS 6/14.001 / 1 byte 0...255 5.001
+ 5.001:self.encodeDPT501, # PDT_SCALING
+ 5.005:self.encodeDPT5, # DPT_DecimalFactor
+ 5.010:self.encodeDPT5, # DPT_Value_1_Ucount
+ 6:self.encodeDPT6, # EIS 14.000 / 1 byte -128 ... 127
+ 7:self.encodeDPT7, # EIS 10.000 / 2 byte 0....65535
+ 8:self.encodeDPT8, # EIS 10.001 / 2 byte -32768 .... 32767
+ 9:self.encodeDPT9, # EIS 5 / 2 byte Float
+ 10:self.encodeDPT10, # EIS 3 / 3 byte WoTag/Stunde/Minute/Sekunde
+ 11:self.encodeDPT11, # EIS 4 / 3 byte Tag/Monat/Jahr
+ 12:self.encodeDPT12, # EIS 11.000 / 4 byte unsigned [0...4.294.967.295]
+ 13:self.encodeDPT13, # EIS 11.001 / 4 byte signed -2.147.483.648 ... 2.147.483.647]
+ 14:self.encodeDPT14, # EIS 9 / 4 byte float
+ 16:self.encodeDPT16 # EIS 15 / 14 byte Text
+ }
def decode(self,raw,dptid=0,dsobj=False):
@@ -52,8 +74,8 @@
elif dsobj:
if "dptid" in dsobj.config:
dpt = dsobj.config['dptid']
- else:
- return False
+ #else:
+ # return False
if dpt == -1:
dpt = self.guessType(raw)
if dsobj:
@@ -63,6 +85,18 @@
return raw
return self._decode(raw,dpt)
+ def encode(self,msg,dptid=0,dsobj=False):
+ dpt=-1
+ if dptid > 0:
+ dpt = dptid
+ elif dsobj:
+ if "dptid" in dsobj.config:
+ dpt = dsobj.config['dptid']
+ else:
+ return False
+ return self._encode(msg,dpt)
+
+
def _decode(self,raw,dpt):
try:
try:
@@ -75,9 +109,22 @@
except:
self.errormsg()
return raw
+
+ def _encode(self,msg,dpt):
+ try:
+ try:
+ return self.ENCODER[dpt](msg)
+ except KeyError:
+ try:
+ return self.ENCODER[int(dpt)](msg)
+ except KeyError:
+ return msg
+ except:
+ self.errormsg()
+ return msg
def errormsg(self,msg=False):
- self.WG.errormsg(msg)
+ self.WG.errorlog(msg)
def debug(self,msg):
self.log(msg,'debug')
@@ -87,6 +134,18 @@
instance = "dpt-types"
self.WG.log(msg,severity,instance)
+ def toByteArray(self,val,length):
+ ## Set ByteArray
+ ret = [0 for b in range(length)]
+ for val in struct.pack("L",val):
+ ## Fill up from end
+ length -= 1
+ ## if struct larger then len return
+ if length < 0:
+ return ret
+ ## write from end to start
+ ret[length] = ord(val)
+ return ret
def toBigInt(self,raw):
c=0
@@ -99,7 +158,10 @@
def decodeDPT1(self,raw):
return int(raw[0]) & 0x1
-
+
+ def encodeDPT1(self,val):
+ pass
+
def decodeDPT2(self,raw):
## 2 Bit Control
## RRRRRRCS
@@ -108,6 +170,9 @@
## S Switch 0=off/1=on
return int(raw[0]) & 0x3
+ def encodeDPT2(self,val):
+ pass
+
def decodeDPT3(self,raw):
## 4 bit Dim (DPT 3.007)
## RRRRDSSS
@@ -116,34 +181,55 @@
## S Step (1-7) 0=Break
## FIXME: dont know what a Datastore should accept here
return int(raw[0]) & 0xf
+
+ def encodeDPT3(self,val):
+ pass
def decodeDPT4(self,raw):
## 1 Byte Character
return chr(raw[0] & 0xff)
+ def encodeDPT4(self,val):
+ pass
+
def decodeDPT5(self,raw):
## 1 Byte unsigned
return (int(raw[0] & 0xff))
+ def encodeDPT5(self,val):
+ pass
+
def decodeDPT501(self,raw):
## 1 Byte unsigned percent
self.debug("DPT5.001 Scaling: value: %d" % raw[0])
return int(raw[0] & 0xff) * 100 / 255
+
+ def encodeDPT501(self,val):
+ pass
def decodeDPT6(self,raw):
## 1 Byte signed
val = int(raw[0] & 0xff)
return (val > 127 and val - 256 or val)
+
+ def encodeDPT6(self,val):
+ pass
def decodeDPT7(self,raw):
## 2 byte unsigned
return int(self.toBigInt(raw) & 0xffff)
+
+ def encodeDPT7(self,val):
+ pass
def decodeDPT8(self,raw):
## 2 Byte signed
val = int(self.toBigInt(raw) & 0xffff)
return (val > 32767 and val - 32768 or val)
+ def encodeDPT8(self,val):
+ pass
+
def decodeDPT9(self,raw):
## 2 Byte Float
## SEEEEMMM MMMMMMMM
@@ -160,6 +246,19 @@
self.debug("DPT9: value: %d sign: %d exp: %d mant: %f" % (val, sign,exp,mant))
return (1 << exp) * 0.01 * mant
+ def encodeDPT9(self,val):
+ sign = 0
+ exp = 0
+ if val < 0:
+ sign = 0x8000
+ mant = val * 100
+ while mant > 2047:
+ mant = mant >> 1
+ exp +=1
+ data = sign | (exp << 11) | (int(mant) & 0x07ff)
+ ## change to 2Byte bytearray
+ return self.toByteArray(data,2)
+
def decodeDPT10(self,raw):
## 3 Byte Time
@@ -177,6 +276,9 @@
## Fixme: eigentlich sollte Zeit als Unix Timestamp gespeichert werden, was macht man mit dem Wochentag
## machs erstmal so wie makki
return "%s %d:%d:%d" % (weekdays[weekday], hour,min,sec)
+
+ def encodeDPT10(self,val):
+ pass
def decodeDPT11(self,raw):
## 3 byte Date
@@ -194,12 +296,22 @@
year += 1900
return "%02d.%02d.%04d" % (day,mon,year)
+ def encodeDPT11(self,val):
+ pass
+
def decodeDPT12(self,raw):
return int(self.toBigInt(raw)) % 0xffffffff
+
+ def encodeDPT12(self,val):
+ pass
+
def decodeDPT13(self,raw):
val = int(self.toBigInt(raw)) % 0xffffffff
return (val > 2147483647 and val - 2147483648 or val)
+ def encodeDPT13(self,val):
+ pass
+
def decodeDPT14(self,raw):
## 4 Byte Float
## SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF
@@ -215,6 +327,9 @@
self.debug("DPT14: value: %d sign: %d exp: %d mant: %f" % (val, sign,exp,mant))
return (1 << exp) * 0.01 * mant
+ def encodeDPT14(self,val):
+ pass
+
def decodeDPT16(self,raw):
res = ""
for char in raw:
@@ -224,6 +339,9 @@
res += chr(char)
return res
+ def encodeDPT16(self,val):
+ pass
+
def validTypes(self,datalen):
##TODO:
ret = []
Modified: PyWireGate/trunk/knx_connector/KNX_Connector.py
===================================================================
--- PyWireGate/trunk/knx_connector/KNX_Connector.py 2010-11-04 10:54:37 UTC (rev 71)
+++ PyWireGate/trunk/knx_connector/KNX_Connector.py 2010-11-04 13:27:57 UTC (rev 72)
@@ -18,11 +18,17 @@
from connector import Connector
+import re
import EIBConnection
import select
import BusMonitor
import GroupSocket
+import DPT_Types
+KNXREADFLAG = 0x00
+KNXRESPONSEFLAG = 0x40
+KNXWRITEFLAG = 0x80
+
class knx_connector(Connector):
CONNECTOR_NAME = 'KNX Connector'
CONNECTOR_VERSION = 0.2
@@ -37,7 +43,10 @@
self.KNXDst = EIBConnection.EIBAddr()
self.busmon = BusMonitor.busmonitor(WireGateInstance,self)
self.groupsocket = GroupSocket.groupsocket(WireGateInstance,self)
+ self.dpt = DPT_Types.dpt_type(WireGateInstance)
+ self.GrpAddrRegex = re.compile(r"(?:|(\d+)\x2F)(\d+)\x2F(\d+)$",re.MULTILINE)
+
## Deafaultconfig
defaultconfig = {
'url':'ip:127.0.0.1',
@@ -115,6 +124,33 @@
self.busmon.decode(self.KNXBuffer.buffer)
+ def str2grpaddr(self,addrstr):
+ grpaddr = self.GrpAddrRegex.findall(addrstr)
+ if not grpaddr:
+ return False
+ ## regex result 1
+ grpaddr = grpaddr[0]
+ addr = 0
+ ## if GROUP3 Addr
+ if grpaddr[0]:
+ addr = int(grpaddr[0]) << 11
+ addr = addr | (int(grpaddr[1]) << 8)
+ addr = addr | int(grpaddr[2])
+ return addr
+
- def send(self,dsobj):
- print "SEND to %s" % dsobj.name
\ No newline at end of file
+ def send(self,msg,dstaddr):
+ try:
+ addr = self.str2grpaddr(dstaddr)
+ if addr:
+ msg = [0,KNXWRITEFLAG] +msg
+ self.KNX.EIBSendGroup(addr,msg)
+ except:
+ self.errormsg("Failed send %r to %r" % (msg,dstaddr))
+
+ def setValue(self,dsobj,msg=False):
+ if not msg:
+ msg = dsobj.getValue()
+ self.debug("SEND %r to %s (%s)" % (msg,dsobj.name,dsobj.id))
+ self.send(self.dpt.encode(msg,dsobj=dsobj),dsobj.id)
+
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ni...@us...> - 2010-11-11 14:37:08
|
Revision: 105
http://openautomation.svn.sourceforge.net/openautomation/?rev=105&view=rev
Author: nilss1
Date: 2010-11-11 14:37:02 +0000 (Thu, 11 Nov 2010)
Log Message:
-----------
Fix 14Byte encoding
Modified Paths:
--------------
PyWireGate/trunk/knx_connector/DPT_Types.py
PyWireGate/trunk/knx_connector/KNX_Connector.py
Modified: PyWireGate/trunk/knx_connector/DPT_Types.py
===================================================================
--- PyWireGate/trunk/knx_connector/DPT_Types.py 2010-11-11 08:07:20 UTC (rev 104)
+++ PyWireGate/trunk/knx_connector/DPT_Types.py 2010-11-11 14:37:02 UTC (rev 105)
@@ -96,7 +96,10 @@
elif dsobj:
if "dptid" in dsobj.config:
dpt = dsobj.config['dptid']
- else:
+ if dpt == -1:
+ dpt = self.guessDPT(msg)
+ #return False
+ if dpt == 0:
return False
return self._encode(msg,dpt)
@@ -438,6 +441,7 @@
return res.decode('iso-8859-15')
def encodeDPT16(self,val):
+ self.debug("DPT16encode: %r (%s)" % (val,type(val)))
if type(val) == unicode:
val = val.encode('iso-8859-15')
## max 14
@@ -478,9 +482,22 @@
## 14byte String
return 16
return 0
+ def guessDPT(self,raw):
+ if type(raw) == int:
+ if raw < 256:
+ return 5
+ elif raw < 655535:
+ return 7
+ elif type(raw) == float:
+ if raw > -671088.64 and raw < 670760.96:
+ return 9
+ else:
+ return 14
+ elif type(raw) == str or type(raw) == unicode:
+ return 16
+ return 0
-
if __name__ == "__main__":
dpttypes = dpt_type(False)
print dpttypes.decode([24,88],dptid=9)
Modified: PyWireGate/trunk/knx_connector/KNX_Connector.py
===================================================================
--- PyWireGate/trunk/knx_connector/KNX_Connector.py 2010-11-11 08:07:20 UTC (rev 104)
+++ PyWireGate/trunk/knx_connector/KNX_Connector.py 2010-11-11 14:37:02 UTC (rev 105)
@@ -174,13 +174,17 @@
def send(self,msg,dstaddr):
try:
- if type(msg) <> list:
- self.log("Failed send %r to %r" % (msg,dstaddr),'warn')
- return
addr = self.str2grpaddr(dstaddr)
if addr:
- msg = [0,KNXWRITEFLAG] + msg
- self.sendQueue.put((addr,msg))
+ apdu = [0]
+ if type(msg) == int:
+ apdu.append(KNXWRITEFLAG | msg)
+ elif type(msg) == list:
+ apdu = apdu +[KNXWRITEFLAG]+ msg
+ else:
+ self.WG.errorlog("invalid Message %r to %r" % (msg,dstaddr))
+ return
+ self.sendQueue.put((addr,apdu))
#self.KNX.EIBSendGroup(addr,msg)
except:
self.WG.errorlog("Failed send %r to %r" % (msg,dstaddr))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ni...@us...> - 2010-11-15 21:21:28
|
Revision: 132
http://openautomation.svn.sourceforge.net/openautomation/?rev=132&view=rev
Author: nilss1
Date: 2010-11-15 21:21:16 +0000 (Mon, 15 Nov 2010)
Log Message:
-----------
added reading and readflag in datastore object config
Modified Paths:
--------------
PyWireGate/trunk/knx_connector/GroupSocket.py
PyWireGate/trunk/knx_connector/KNX_Connector.py
Modified: PyWireGate/trunk/knx_connector/GroupSocket.py
===================================================================
--- PyWireGate/trunk/knx_connector/GroupSocket.py 2010-11-15 21:20:31 UTC (rev 131)
+++ PyWireGate/trunk/knx_connector/GroupSocket.py 2010-11-15 21:21:16 UTC (rev 132)
@@ -57,16 +57,21 @@
##FIXME: unknown APDU
self.debug("unknown APDU from "+msg['srcaddr']+" to "+msg['dstaddr']+ " raw:"+buf)
else:
+ dsobj = self.WG.DATASTORE.get(id)
if (buf[1] & 0xC0 == 0x00):
msg['type'] = "read"
+ if dsobj.config.get('readflag',False):
+ self.debug("Read from %s" % id)
+ self._parent.setValue(dsobj,flag=0x40)
+
##FIXME: Check (ds) if we should respond
- elif (buf[1] & 0xC0 == 0x40):
- msg['type'] = "response"
- ##FIXME: Update ds also?
- elif (buf[1] & 0xC0 == 0x80):
- msg['type'] = "write"
+ elif (buf[1] & 0xC0 == 0x40) or (buf[1] & 0xC0 == 0x80):
+ if (buf[1] & 0xC0 == 0x40):
+ msg['type'] = "response"
+ else:
+ msg['type'] = "write"
## search Datastoreobject
- dsobj = self.WG.DATASTORE.get(id)
+
## Decode the DPT Value
if (len(buf) >2):
msg['value'] = self.dpt.decode( buf[2:],dsobj=dsobj)
@@ -94,7 +99,7 @@
def log(self,msg,severity='info',instance=False):
if not instance:
- instance = self.instanceName
+ instance = 'KNX'
self._parent.log(msg,severity,instance)
def debug(self,msg):
Modified: PyWireGate/trunk/knx_connector/KNX_Connector.py
===================================================================
--- PyWireGate/trunk/knx_connector/KNX_Connector.py 2010-11-15 21:20:31 UTC (rev 131)
+++ PyWireGate/trunk/knx_connector/KNX_Connector.py 2010-11-15 21:21:16 UTC (rev 132)
@@ -172,15 +172,15 @@
- def send(self,msg,dstaddr):
+ def send(self,msg,dstaddr,flag=KNXWRITEFLAG):
try:
addr = self.str2grpaddr(dstaddr)
if addr:
apdu = [0]
if type(msg) == int:
- apdu.append(KNXWRITEFLAG | msg)
+ apdu.append(flag | msg)
elif type(msg) == list:
- apdu = apdu +[KNXWRITEFLAG]+ msg
+ apdu = apdu +[flag]+ msg
else:
self.WG.errorlog("invalid Message %r to %r" % (msg,dstaddr))
return
@@ -189,12 +189,12 @@
except:
self.WG.errorlog("Failed send %r to %r" % (msg,dstaddr))
- def setValue(self,dsobj,msg=False):
+ def setValue(self,dsobj,msg=False,flag=KNXWRITEFLAG):
try:
if not msg:
msg = dsobj.getValue()
self.debug("SEND %r to %s (%s)" % (msg,dsobj.name,dsobj.id))
- self.send(self.dpt.encode(msg,dsobj=dsobj),dsobj.id)
+ self.send(self.dpt.encode(msg,dsobj=dsobj),dsobj.id,flag=flag)
except:
print "----------- ERROR IN KNX_CONNECTOR.setValue ----------------"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|