Hi Heicar,
ich bin spät drann, nach einem 18 Stunden Tag.
Es freut mich, dass es mit dem USB-CAB doch funktioniert
Der Preis dieses Kabels ist aber m.E. unverhältnissmässig hoch, deshalb hätte ich mich gefreut, wenn sich andere Wege finden ließen.
Das bleibt wohl für später offen...
So, nun zu deinen Fragen (ganz kurz, weil müde):
Ich rate Dir davon ab, einzelne Merker(-Bit) abzufragen. Versuche in deinem Easy Programm alle Merker so dicht wie möglich zusammenzuführen (d.h. benachbarte Merker verwenden).
Z.B. kannst Du dann M1 bis M32 mit nur einem Aufruf von MD1.get_value() auslesen. Der 32 bit Integer den du bekommst, braucht dann ein bisschen Dekodierung, um die einzelnen Bits auszulesen, das geht aber relativ einfach.
Am besten ist wenn man solche Aufgaben dem Fernrechner überlässt (z.B. mittels JavaScript), das spart dem Raspy Arbeit, vor allen dingen wenn mehrere Clients auf einmal etwas von ihm wollen.
Dann gibt es noch die Methode get_values() - anstatt get_value() - die gibt dir, mit einer einzigen Abfrage, gleich 32 byte aus dem Speicherbereich zurück...
Es sind noch andere Funktionen verfügbar, die die Sache erleichtern könnten:
Jede plc_item Instanz kann Ihren Wert selbstständig ins Netzwerk schicken, so dass alle Rechner - die auf diesen Port hören - sie empfangen (broadcasting).
Dafür sind die Übergabeparameter bc_port und bias da:
Wenn der vorherige Wert des plc_items sich um mindestens den Wert bias ändert, schickt er automatisch seinen neuen Wert ins Netz, über bc_port.
Der Haken ist: plc_item tut sich erst "updaten" wenn get_value() aufgerufen wird...
Ich habe da einen Socket-Server Script, der auf meinem Raspi als Dienst läuft. Das Skript benutzt die com_lib.py um mit der Easy zu kommunizieren (also com_lib.py in den selben Ordner werfen), und sockets um mit anderen (lokalen oder fernen) Prozessen zu kommunizieren:
#!/usr/bin/env python
# IPC_TO_SERIAL.py #140416 -------------------------------------------
#
# socketserver for com_lib.py
#----------------------------------------------------------------------
import com_lib as com_lib
import os
import socket
import select
import struct
import serial
import sys
import time
import atexit
time.sleep(10)
res = com_lib.set_device_baudrate(57600)
if res == 0:
print com_lib.o_serial
com_lib.close_port()
# ------------------------------------------ default plc_items ---------------------------------------
for index in range(1,97):
exec('M'+str(index)+'=com_lib.plc_item(0,\"M\",'+str(index)+')')
exec('MB'+str(index)+'=com_lib.plc_item(0,\"MB\",'+str(index)+')')
exec('MW'+str(index)+'=com_lib.plc_item(0,\"MW\",'+str(index)+')')
exec('MD'+str(index)+'=com_lib.plc_item(0,\"MD\",'+str(index)+')')
for index in range(1,13):
exec('I'+str(index)+'=com_lib.plc_item(0,\"I\",'+str(index)+')')
for index in range(1,9):
exec('Q'+str(index)+'=com_lib.plc_item(0,\"Q\",'+str(index)+')')
for index in range(1,5):
exec('IA'+str(index)+'=com_lib.plc_item(0,\"IA\",'+str(index)+')')
QA = com_lib.plc_item(0,'QA',1)
# -------- subscriptions --------
subscribed_items = []
def subscribe_item(_item,_port,_max_age=1,_bias=0):
_item.port = _port
_item.max_age = _max_age
_item.bias = _bias
subscribed_items.append(_item)
def unsubscribe_item(_item):
_item.port = None
subscribed_items.remove(_item)
subscribe_item(Q1,54000,.1)
subscribe_item(IA1,54000,1.5,10)
subscribe_item(MD1,54000,2)
subscribe_item(MD89,54000,3)
def get_interfaces():
resp =[]
for item in subscribed_items:
tmp_item = (item.item_type+str(item.index+1),item.port,item.max_age,item.bias)
resp.append(tmp_item)
return resp
# ------------------ serial ----
s_name='/dev/ttyUSB0'
s_baudrate=9600
s_timeout=1
def set_serial(_name,_baudrate,_timeout):
global s_name,s_baudrate,s_timeout
s_name = _name
s_baudrate = _baudrate
s_timeout = _timeout
# ------------------------- raw socket to serial com -----------------
def write_port(outData):
try:
if com_lib.o_serial.inWaiting() > 0:
com_lib.urb.append(com_lib.o_serial.read(com_lib.o_serial.inWaiting())) # --- flush unrequested data to urb
com_lib.o_serial.write(outData)
return listen_port() # --- go wait for data
except:
return 4 # --- no port?
def listen_port():
try:
cnt = 0
while cnt < 500 :
data_len=com_lib.o_serial.inWaiting()
if data_len > 6: #( ---- smallest message 'e'/len/err_1/err_2/crc_1/crc_2
in_packet = com_lib.o_serial.read(2)
tupl = struct.unpack('<sB',in_packet)
if tupl[0] == 'e':
pl_len = int(tupl[1])
in_packet = in_packet+com_lib.o_serial.read(pl_len)
return in_packet
else:
in_packet = in_packet+com_lib.o_serial.read(com_lib.o_serial.inWaiting())
return in_packet
else:
cnt=cnt+1
return 8 # ---- function timed out
except:
return 9 # ---- tty port is closed or does not exist
# ----------------- sockets --------------------------------------
# ----------------------------------------------------------------
# ----------------- socket server --------------------------------
client_objects = []
size = 1024
# setup variables and server sockets (UNIX and INET)
unix_sock = '/tmp/raspy_com'
# clean up for nix
if os.path.exists(unix_sock):
os.remove(unix_sock)
# server sockets
unix_backlog = 5
tcp_host = None
# ------ get LAN address ----------------------------------
if tcp_host == None:
if os.name != "nt":
import fcntl
def get_interface_ip(ifname):
ts = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(ts.fileno(), 0x8915, struct.pack('256s',ifname[:15]))[20:24])
tcp_host = socket.gethostbyname(socket.gethostname())
if tcp_host.startswith('127.'):
interfaces = ['eth0','eth1','eth2','wlan0','wlan1','wifi0','ath0','ath1','ppp0',]
for ifname in interfaces:
try:
tcp_host = get_interface_ip(ifname)
break
except IOError:
tcp_host = 'localhost'
pass
# ---------------------------------------------------------
def close_sockets():
print 'closing sockets'
for socket in client_objects:
socket.close()
atexit.register(close_sockets)
tcp_port = 50000
tcp_backlog = 5
got_nix_server = False
server_count = 0
try :
unix_server = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
unix_server.setblocking(0)
unix_server.bind(unix_sock)
unix_server.listen(unix_backlog)
client_objects.append(unix_server)
server_count = 1
got_nix_server = True
print 'Unix Socket Server listening at '+unix_sock
except:
print str(os.name)+' seems not to implement the AF_UNIX family.'
tcp_server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcp_server.setblocking(0)
tcp_server.bind((tcp_host,tcp_port))
tcp_server.listen(tcp_backlog)
client_objects.append(tcp_server)
server_count = server_count + 1
print 'TCP Socket Server listening at '+str(tcp_host)+':'+str(tcp_port)
com_lib.open_port()
# ------------------------ main -----------------------------
running = 1
while running:
if len(client_objects) > server_count:
startTime = time.time()
for item in subscribed_items:
if item.timestamp < startTime - item.max_age:
#print 'updating item '+item.item_type+str(item.index+1)
res = item.get_value()
input_ready,output_ready,in_error = select.select(client_objects,[],client_objects,.01)
for rc in input_ready:
if rc == unix_server:
client,address = unix_server.accept()
client_objects.append(client)
if com_lib.o_serial == None:
res = com_lib.open_port()
client.send(str(len(client_objects)-2))
print 'new NIX client '+str(len(client_objects)-2)+' connected to socket '+unix_sock
elif rc == tcp_server:
client,address = tcp_server.accept()
client_objects.append(client)
if com_lib.o_serial == None:
res = com_lib.open_port()
client.send(str(len(client_objects)-2))
print 'new TCP client #'+str(len(client_objects)-2)+' connected by '+str(address)
else:
try:
sock_type = rc.family
sock_address = rc.getpeername()
data = rc.recv(size)
except:
data = False
if data:
if data[0] == 'E':
res = write_port(data)
rc.send(str(res))
else:
try:
exec('res='+data)
rc.send(str(res))
except:
rc.send('?')
else:
rc.close()
client_objects.remove(rc)
if len(client_objects) <= server_count:
print 'nobody connected... closing serial port'
com_lib.close_port()
for rc in in_error:
rc.close()
client_objects.remove(rc)
Dieses Skript Instanziert am Anfang alle M, MB, MD, Q, A die auf einer 822er zur Verfügung stehen.
Später werden, nmittels subscribe_item() einige davon mit einem Port, einem bias und einem max_age (maximales alter) versehen, so dass sie automatisch geupdated werden (fürchterliches wort).
Es ist heute zu spät um das zu erklären ... (gääähhn...) aber vielleicht kannst Du reinschauen, es anpassen und mit rumspielen.
Ich verspreche mehr information demnächst...
Ach so, ein einfacher Client für die broadcast Pakete:
# -------- udp broadcast receiver ------
MY_PORT = 54000
import sys
from socket import *
s = socket(AF_INET,SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_REUSEADDR,1)
s.bind(('',MY_PORT))
while 1:
data,wherefrom = s.recvfrom(1500,0)
print data,wherefrom
Gute Nacht + und vielen Dank für deine Geduld!
Gruß,
Peter