I've tried to make an example code to reproduce the failure
import datetime
import struct
from time import sleep
def set_real(_bytearray, byte_index, real):
"""
Set Real value
make 4 byte data from real
"""
real = float(real)
real = struct.pack('>f', real)
_bytes = struct.unpack('4B', real)
for i, b in enumerate(_bytes):
_bytearray[byte_index + i] = b
def get_real(_bytearray, byte_index):
"""
Get real value. create float from 4 bytes
"""
x = _bytearray[byte_index:byte_index + 4]
real = struct.unpack('>f', struct.pack('4B', *x))[0]
return real
byte = bytearray(70) # Dataarray
while True:
x = int(datetime.datetime.now().strftime("%S"))
byte[x] = int(datetime.datetime.now().strftime("%S"))
print byte[x]
print byte[x-1] # read a different byte test if value still in memory
value = 0.3333
set_real(byte, 65, value)
print get_real(byte , 65)
sleep(0.5)
But this example doesn't give the failure, so it's something else I think.
My code for the program I give in the next part. But I think it is difficult to test it for others because it reading out my smart power supply meter and sending the value's to a Siemens PLC with a library called Snap7, the functions like set_real are in the libary. I'n the example above there is a part of the source for the set_real function.
# DSMR v4.2 p1 uitlezen
# (c) 10-2012 - 2016 GJ - gratis te kopieren en te plakken
versie = "1.1"
import sys
import serial
import snap7
from snap7.util import *
import struct
##############################################################################
#Main program
##############################################################################
#Set COM port config
ser = serial.Serial()
ser.baudrate = 115200
ser.bytesize=serial.EIGHTBITS
ser.parity=serial.PARITY_NONE
ser.stopbits=serial.STOPBITS_ONE
ser.xonxoff=0
ser.rtscts=0
ser.timeout=50
ser.port="/dev/ttyUSB0"
#Set plc
plc = snap7.client.Client()
byte = bytearray(57) # Dataarray
while True:
#byte = bytearray(57) # Dataarray
#Open PLC connection
try:
plc.connect("192.168.178.100",0,2)
#print "Connected to PLC"
except:
error.error("Connection PLC lost")
pass
#Open COM port
try:
ser.open()
except:
sys.exit ("Fout bij het openen van %s. Aaaaarch." % ser.name)
#Initialize
#p1_teller is mijn tellertje voor van 0 tot 38 te tellen
p1_teller=0
while p1_teller < 38:
p1_line=''
#Read 1 line van de seriele poort
try:
p1_raw = ser.readline()
except:
sys.exit ("Seriele poort %s kan niet gelezen worden. Aaaaaaaaarch." % ser.name )
p1_str=str(p1_raw)
p1_line=p1_str.strip()
if p1_line[0:9] == "1-0:1.8.1":
set_real(byte, 0, float(p1_line[10:20]))
print "daldag ", float(p1_line[10:20]), " kWh"
elif p1_line[0:9] == "1-0:1.8.2":
set_real(byte, 4, float(p1_line[10:20]))
print "piekdag ", float(p1_line[10:20]), " kWh"
elif p1_line[0:9] == "1-0:2.8.1":
set_real(byte, 8, float(p1_line[10:20]))
print "dalterug ", float(p1_line[10:20]), " kWh"
elif p1_line[0:9] == "1-0:2.8.2":
set_real(byte, 12, float(p1_line[10:20]))
print "piekterug ", float(p1_line[10:20]), " kWh"
elif p1_line[0:11] == "0-0:96.14.0":
set_int(byte, 16, int(p1_line[15:16]))
if int(p1_line[15:16]) == 1:
print "Piek/Dal Tarief: Dal"
elif int(p1_line[15:16]) == 2:
print "Piek/Dal Tarief: Piek"
elif p1_line[0:9] == "1-0:1.7.0":
set_int(byte, 18, int(float(p1_line[10:16])*1000))
print "Act. vermogen ", int(float(p1_line[10:16])*1000), " W"
elif p1_line[0:9] == "1-0:2.7.0":
set_int(byte, 20, int(float(p1_line[10:16])*1000))
print "Act. vermogen terug ", int(float(p1_line[10:16])*1000), " W"
elif p1_line[0:10] == "1-0:32.7.0":
set_real(byte, 22, float(p1_line[11:16]))
print "Voltage L1 ", float(p1_line[11:16]), "V"
elif p1_line[0:10] == "1-0:52.7.0":
set_real(byte, 26, float(p1_line[11:16]))
print "Voltage L2 ", float(p1_line[11:16]), "V"
elif p1_line[0:10] == "1-0:72.7.0":
set_real(byte, 30, float(p1_line[11:16]))
print "Voltage L3 ", float(p1_line[11:16]), "V"
elif p1_line[0:10] == "1-0:31.7.0":
set_int(byte, 34, int(p1_line[11:14]))
print "Current L1 ", int(p1_line[11:14]), "A"
elif p1_line[0:10] == "1-0:51.7.0":
set_int(byte, 36, int(p1_line[11:14]))
print "Current L2 ", int(p1_line[11:14]), "A"
elif p1_line[0:10] == "1-0:71.7.0":
set_int(byte, 38, int(p1_line[11:14]))
print "Current L3 ", int(p1_line[11:14]), "A"
elif p1_line[0:10] == "1-0:21.7.0":
set_int(byte, 40, int(float(p1_line[11:17])*1000))
print "Power L1 ", int(float(p1_line[11:17])*1000), " W"
elif p1_line[0:10] == "1-0:41.7.0":
set_int(byte, 42, int(float(p1_line[11:17])*1000))
print "Power L2 ", int(float(p1_line[11:17])*1000), " W"
elif p1_line[0:10] == "1-0:61.7.0":
set_int(byte, 44, int(float(p1_line[11:17])*1000))
print "Power L3 ", int(float(p1_line[11:17])*1000), " W"
elif p1_line[0:10] == "1-0:22.7.0":#(00.000*kW)
set_int(byte, 46, int(float(p1_line[11:17])*1000))
print "Geleverd vermogen L1: ", int(float(p1_line[11:17])*1000), " W"
elif p1_line[0:10] == "1-0:42.7.0":#(00.000*kW)
set_int(byte, 48, int(float(p1_line[11:17])*1000))
print "Geleverd vermogen L2: ", int(float(p1_line[11:17])*1000), " W"
elif p1_line[0:10] == "1-0:62.7.0":#(00.000*kW)
set_int(byte, 50, int(float(p1_line[11:17])*1000))
print "Geleverd vermogen L3: ", int(float(p1_line[11:17])*1000), " W"
elif p1_line[0:10] == "0-1:24.2.1":#(180216191004W)(00000.004*m3)
set_real(byte, 52, float(p1_line[26:35]))
print "Gasstand: ", float(p1_line[26:35]), " m3"
p1_teller = p1_teller +1
#Close port and show status
try:
ser.close()
except:
sys.exit ("Oops %s. Programma afgebroken. Kon de seriele poort niet sluiten." % ser.name )
#Send Data to PLC
#set_int(byte, 56, 1) #Set value 1 in byte 56, to PLC as mark new data recieved
byte[56] = 1 #Set value 1 in byte 56, to PLC as mark new data recieved
byte = plc.db_write(11, 600, byte)
plc.disconnect()
The Error is the next
Error:
Traceback (most recent call last):
File "/home/pi/Projects/Slimme Meter uitlezen/test4.py", line 64, in <module>
set_real(byte, 4, float(p1_line[10:20]))
File "/usr/local/lib/python2.7/dist-packages/snap7/util.py", line 163, in set_real
_bytearray[byte_index + i] = b
TypeError: 'NoneType' object does not support item assignment