#!/usr/bin/env python3
 
+# section: environment {{{1
+#####################################################
+import gf_config as gf
 #import serial
 import fileinput
 import matplotlib.pyplot as plt
 import numpy as pl
 from datetime import datetime,date,time
-from math import modf
 
+
+# section: process_timestamp {{{1
 ######################################################
 def process_timestamp(line):
   info=line.split(":")
     except:
       pass
   print("Timestamp:",ts)
-  print(line)
   return ts,line
 
+# section: checkline {{{1
 ######################################################
 def checkline(line):
   ok=False
   print("Ok:",ok)
   return ok
 
+# section: readbyte {{{1
 ######################################################
-# read next byte from line
 def readbyte(line):
-  byte=256
-  while byte==256 and len(line)>0:
+  byte=-1
+  while byte==-1 and len(line)>0:
     try:
       byte=int(line[0:2],16)
       line=line[1:]
       line=line[2:]
   return byte,line
 
+# section: process_head {{{1
 ######################################################
 def process_head(line):
-  ds,line=readbyte(line)
-  if ds==0x27:
-    typ="Data Request"
-  elif ds==0x26:
-    typ="Data Message"
-  elif ds==0x24:
-    typ="Data Reply"
+  sd,line=readbyte(line)
+  if sd==gf.DATA_REQUEST:
+    typ="DATA_REQUEST --->"
+  elif sd==gf.DATA_MESSAGE:
+    typ="DATA_MESSAGE --->"
+  elif sd==gf.DATA_REPLY:
+    typ="<--- DATA_REPLY"
   else:
-    typ="Data Error"
-    print("Type:",typ,"DS:",ds)
-    return typ,ds,0,0,0,line
+    typ="**** DATA_ERROR ****"
+    print("Data Type:",typ,"Start Delimiter:",sd)
+    return typ,sd,0,0,0,line
   le,line=readbyte(line)
   da,line=readbyte(line)
   sa,line=readbyte(line)
-  if ds==0x27 and da==0xFE:
-    typ="Connection Request"
-  if ds==0x27 and da==0xFF:
-    typ="Broadcast Request"
-  if ds==0x26 and da==0xF7:
-    typ="Multicast Message"
-  print("Type:",typ,"Length:",le,"Destination:",da,"Source:",sa)
-  return typ,ds,le,da,sa,line
+  if sd==gf.DATA_REQUEST and da==0xFE:
+    typ="CONNECTION_REQUEST ===>"
+  if sd==gf.DATA_REQUEST and da==0xFF:
+    typ="DATA_REQUEST  ===>"
+  if sd==gf.DATA_MESSAGE and da==0xF7:
+    typ="DATA_MESSAGE  ===>"
+  print(typ)
+  print("Length:",le,"Destination Addr:",da,"Source Addr:",sa)
+  return typ,sd,le,da,sa,line
 
+# section: process_apdu {{{1
 ######################################################
 def process_apdu(line):
   cl,line=readbyte(line)
-  cl=cl&0xF
+  cl=cl&0x1F
   le,line=readbyte(line)
   os=(le&0xC0)>>6
   le=le&0x3F
   print("Class:",cl,"Operation:",os,"Length:",le)
   return cl,os,le,line
 
+# section: process_data {{{1
+######################################################
+def process_data(line,le,size1,size2):
+  num=int(le/(size1+size2))
+  ids=[0]*num
+  val=[0]*num
+  for i in range(0,num):
+    if size1>0:
+      ids[i],line=readbyte(line)
+    for j in range(0,size2):
+      tmp,line=readbyte(line)
+      val[i]=(val[i]<<8)+tmp
+    if size1>0 and size2>0:
+      print("Id:",ids[i], "Value:",val[i])
+    elif size1>0:
+      print("Id:",ids[i])
+    elif size2>0:
+      print("Value:",val[i])
+  return ids,val,line
+
+
+# section: process_string {{{1
 ######################################################
-def process_class5(line,numid):
-  id=[0]*numid
-  val=[0]*numid
-  for i in range(0,numid):
-    id[i],line=readbyte(line)
+def process_string(line,le):
+  val=[0]*le
+  ids,line=readbyte(line)
+  for i in range(0,le-1):
     val[i],line=readbyte(line)
-    print("Id:",id[i],"Value:",val[i])
-  return id,val,line
+  string=''.join(chr(i) for i in val)
+  print("Id:",ids, "Value:",string)
+  return ids,string,line
+
+# section: process_object {{{1
+######################################################
+def process_object(line,le):
+  return ids,val,line
 
+
+# section: process_crc {{{-1
 ######################################################
 def process_crc(line):
   crc1,line=readbyte(line)
   print("CRC:",crc)
   return crc
 
+# section: process_telegram {{{1
+  # section: start {{{2
 ######################################################
-def process(line):
+def process_telegram(line):
   global td
   global master
   global speed
 
   # Check if timestamp exists
   ts,line=process_timestamp(line)
-
   # Check if line is ok
   ok=checkline(line)
   if not ok: return
-
   # Process telegram
   typ,ds,le,da,sa,line=process_head(line)
   numbytes=le-2
   while numbytes>0 and len(line)>=2*numbytes:
     cl,os,ale,line=process_apdu(line)
     numbytes=numbytes-2-ale
-    if cl==5:
-      id5,val5,line=process_class5(line,int(ale/2))
+    # section: class 2 {{{2
+    if cl==2 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids2,val2,line=process_data(line,ale,1,0)
+    elif cl==2 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids2,val2,line=process_data(line,ale,0,1)
+    elif cl==2 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids2,val2,line=process_data(line,ale,1,0)
+    elif cl==2 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids2,val2,line=process_data(line,ale,0,4)
+    # section: class 3 {{{2
+    elif cl==3 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids3,val3,line=process_data(line,ale,1,0)
+    elif cl==3 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids3,val3,line=process_data(line,ale,0,0)
+    elif cl==3 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids3,val3,line=process_data(line,ale,1,0)
+    elif cl==3 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids3,val3,line=process_data(line,ale,0,4)
+    # section: class 4 {{{2
+    elif cl==4 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids4,val4,line=process_data(line,ale,1,0)
+    elif cl==4 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids4,val4,line=process_data(line,ale,0,1)
+    elif cl==4 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids4,val4,line=process_data(line,ale,1,1)
+    elif cl==4 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids4,val4,line=process_data(line,ale,0,0)
+    elif cl==4 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids4,val4,line=process_data(line,ale,1,0)
+    elif cl==4 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids4,val4,line=process_data(line,ale,0,4)
+    # section: class 5 {{{2
+    elif cl==5 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids5,val5,line=process_data(line,ale,1,0)
+    elif cl==5 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids5,val5,line=process_data(line,ale,0,1)
+    elif cl==5 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids5,val5,line=process_data(line,ale,1,1)
+    elif cl==5 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids5,val5,line=process_data(line,ale,0,0)
+    elif cl==5 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids5,val5,line=process_data(line,ale,1,0)
+    elif cl==5 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids5,val5,line=process_data(line,ale,0,4)
       # Debugging
       td=td+[ts.timestamp()]
       master=master+[1+(sa-31)/10]
       for i in range(4):
         speed[i]=speed[i]+[val5[i]/254]
+    # section: class 7 {{{2
+#    elif cl==7:
+#      ids7,val7,line=process_string(line,ale)
+    # section: class 10 {{{2
+#    elif cl==10:
+#      ids10,val10,line=process_object(line,ale)
+    # section: class 11 {{{2
+    elif cl==11 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids11,val11,line=process_data(line,ale,1,0)
+    elif cl==11 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids11,val11,line=process_data(line,ale,0,2)
+    elif cl==11 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids11,val11,line=process_data(line,ale,1,2)
+    elif cl==11 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids11,val11,line=process_data(line,ale,0,0)
+    elif cl==11 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids11,val11,line=process_data(line,ale,1,0)
+    elif cl==11 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids11,val11,line=process_data(line,ale,0,4)
+    # section: class 12 {{{2
+    elif cl==12 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids12,val12,line=process_data(line,ale,1,0)
+    elif cl==12 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids12,val12,line=process_data(line,ale,0,2)
+    elif cl==12 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids12,val12,line=process_data(line,ale,1,2)
+    elif cl==12 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids12,val12,line=process_data(line,ale,0,0)
+    elif cl==12 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids12,val12,line=process_data(line,ale,1,0)
+    elif cl==12 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids12,val12,line=process_data(line,ale,0,4)
+    # section: class 13 {{{2
+    elif cl==13 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids13,val13,line=process_data(line,ale,1,0)
+    elif cl==13 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids13,val13,line=process_data(line,ale,0,2)
+    elif cl==13 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids13,val13,line=process_data(line,ale,1,2)
+    elif cl==13 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids13,val13,line=process_data(line,ale,0,0)
+    elif cl==13 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids13,val13,line=process_data(line,ale,1,0)
+    elif cl==13 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids13,val13,line=process_data(line,ale,0,4)
+    # section: class 14 {{{2
+    elif cl==14 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids14,val14,line=process_data(line,ale,1,0)
+    elif cl==14 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids14,val14,line=process_data(line,ale,0,3)
+    elif cl==14 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids14,val14,line=process_data(line,ale,1,3)
+    elif cl==14 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids14,val14,line=process_data(line,ale,0,0)
+    elif cl==14 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids14,val14,line=process_data(line,ale,1,0)
+    elif cl==14 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids14,val14,line=process_data(line,ale,0,4)
+    # section: class 15 {{{2
+    elif cl==15 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids15,val15,line=process_data(line,ale,1,0)
+    elif cl==15 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids15,val15,line=process_data(line,ale,0,3)
+    elif cl==15 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids15,val15,line=process_data(line,ale,1,3)
+    elif cl==15 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids15,val15,line=process_data(line,ale,0,0)
+    elif cl==15 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids15,val15,line=process_data(line,ale,1,0)
+    elif cl==15 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids15,val15,line=process_data(line,ale,0,4)
+    # section: class 16 {{{2
+    elif cl==16 and ds==gf.DATA_REQUEST and os==gf.OS_GET:
+      ids16,val16,line=process_data(line,ale,1,0)
+    elif cl==16 and ds==gf.DATA_REPLY and os==gf.OS_GET:
+      ids16,val16,line=process_data(line,ale,0,3)
+    elif cl==16 and (ds==gf.DATA_REQUEST or ds==gf.DATA_MESSAGE) and os==gf.OS_SET:
+      ids16,val16,line=process_data(line,ale,1,3)
+    elif cl==16 and ds==gf.DATA_REPLY and os==gf.OS_SET:
+      ids16,val16,line=process_data(line,ale,0,0)
+    elif cl==16 and ds==gf.DATA_REQUEST and os==gf.OS_INFO:
+      ids16,val16,line=process_data(line,ale,1,0)
+    elif cl==16 and ds==gf.DATA_REPLY and os==gf.OS_INFO:
+      ids16,val16,line=process_data(line,ale,0,4)
+    # section: end {{{2
     else:
       line=line[ale*3:]
   crc=process_crc(line)
   return
 
+# section: logging {{{1
 ######################################################
-# Debugging
+
+# global variable
 td=[]
 master=[]
 speed=[]
 
 for line in fileinput.input():
   print("====================================================================")
-  print(line)
-  process(line)
+#  print(line)
+  process_telegram(line)
+
+# section: debugging {{{1
+######################################################
 
 # Calculate timedelta
 if len(td)==0: exit()