node - red serial answer - serial-port

I have a problem with node-red.
As an input I have a serial port input set to 115200bps 8N1.
After received an message in form "st&00&" it will split that message in array of strings. In first string will be that "st" and in the second will be "00". That is working. Directly after that i need to check if first string from that array contains "st" and if yes send response back via serial port. And there is a problem. I am able to send that response but it will take more than 80ms to send it. Do you have any idea how to speed it up?
Thank you
My code:
[{"id":"8bfa007f.4e988","type":"serial in","z":"7a60b001.10afb","name":"","serial":"c68e363c.cfacd8","x":84,"y":128,"wires":[["b63c025e.3e288","e151751a.d6fde8"]]},{"id":"1be68e76.7f0352","type":"debug","z":"7a60b001.10afb","name":"","active":true,"console":"false","complete":"payload","x":599,"y":73,"wires":[]},{"id":"b63c025e.3e288","type":"function","z":"7a60b001.10afb","name":"split to arrays","func":"var vstup = msg.payload;\nvar vystup = vstup.split(\"&\");\nvar data = parseInt(vystup[1]);\nswitch (vystup[0])\n{\n case \"st\": //st = start\n global.set(\"zaciatok\", true);\n global.set(\"zariadenie\", data);\n msg.payload = \"ok\";\n break;\n case \"ok\": //potvrdzovacia sprava\n global.set(\"potvrdenie\", true);\n global.set(\"zariadenie\", data);\n msg.payload = null;\n break;\n case \"sp\": //sp = stop\n global.set(\"koniec\", true);\n global.set(\"zariadenie\", data);\n msg.payload = null;\n break;\n case \"_\":\n global.set(\"hodnota\", true);\n global.set(\"cislo\", data);\n msg.payload = null;\n break;\n}\nreturn msg;","outputs":"1","noerr":0,"x":258,"y":128,"wires":[["7fc79a7f.5ef3b4"]]},{"id":"1f97ffe.6cb02","type":"serial out","z":"7a60b001.10afb","name":"","serial":"c68e363c.cfacd8","x":564,"y":20,"wires":[]},{"id":"67a1de88.afaee","type":"function","z":"7a60b001.10afb","name":"split to OPC","func":"var start = global.get(\"zaciatok\");\nvar ID_zar = global.get(\"zariadenie\");\nvar ok = global.get(\"potvrdenie\");\nvar stop = global.get(\"koniec\");\nvar data = global.get(\"cislo\");\nvar nastav = global.get(\"hodnota\")\nvar msg1 = {};\nvar msg2 = {};\n\nif (start === true)\n{\n msg1 = {\n payload : true,\n topic : \"ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.start\",\n datatype : \"Boolean\",\n browserName : \"\"\n };\n msg2 = {\n payload : ID_zar,\n topic : \"ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.ID_zar\",\n datatype :\"Int16\",\n browserName : \"\"\n };\n global.set(\"zaciatok\",false);\n global.set(\"ID_zar\", 0);\n}\nelse if (stop === true)\n{\n msg1 = {\n payload : true,\n topic : \"ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.stop\",\n datatype : \"Boolean\",\n browserName : \"\"\n };\n msg2 = {\n payload : ID_zar,\n topic : \"ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.ID_zar\",\n datatype :\"Int16\",\n browserName : \"\"\n };\n global.set(\"koniec\",false);\n global.set(\"ID_zar\", 0);\n}\nelse if (nastav === true)\n{\n msg1 = {\n payload : data,\n topic : \"ns=4;s=|var|CODESYS Control for Raspberry Pi SL.Application.GVL.data\",\n datatype : \"Int16\",\n browserName : \"\"\n };\n msg2.payload = null;\n}\nreturn [msg1,msg2];","outputs":"2","noerr":0,"x":526,"y":146,"wires":[["7f8798f8.5574b8"],["7f8798f8.5574b8"]]},{"id":"7f8798f8.5574b8","type":"OpcUa-Client","z":"7a60b001.10afb","endpoint":"c03b2244.09eb4","action":"write","time":10,"timeUnit":"s","name":"","x":720,"y":144,"wires":[[]]},{"id":"7fc79a7f.5ef3b4","type":"function","z":"7a60b001.10afb","name":"","func":"if (msg.payload !== null)\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":32,"wires":[["1f97ffe.6cb02","67a1de88.afaee","1be68e76.7f0352"]]},{"id":"e151751a.d6fde8","type":"debug","z":"7a60b001.10afb","name":"","active":true,"console":"false","complete":"false","x":212,"y":255,"wires":[]},{"id":"c68e363c.cfacd8","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"115200","databits":"8","parity":"none","stopbits":"1","newline":"\\n","bin":"false","out":"char","addchar":true},{"id":"c03b2244.09eb4","type":"OpcUa-Endpoint","z":"","endpoint":"opc.tcp://192.168.1.201:4840","secpol":"None","secmode":"NONE","login":false}]

Related

Send data from Pico W to InfluxDB via urequest

I want to save the wind measurement i record with my raspberry pico w in the InfluxDB, that is hosted on my Raspberry Pi 4b with http-requests. For that i am using the urequest-library
def send_data_to_influxdb(speed):
data = '"Windmeasure,location=outdoor windspeed=' + str(speed) + ' $(date +%s%N)"'
url = 'http://192.168.178.46:8086/write?db=iobroker'
username = 'user_iobroker'
password = '{pwd}'
url = 'http://' + username + ':' + password + '#192.168.178.46:8086/write?db=iobroker'
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
try:
response = urequests.post(url, headers=headers, data=data.encode())
except Exception as e:
print("Error sending data to InfluxDB: ", e)
else:
if response.status_code != 204:
print("Error sending data to InfluxDB. Response code: ", response.status_code)
else:
print("Data sent successfully to InfluxDB.")
response.close()
I get the following error:
Error sending data to InfluxDB: invalid syntax for integer with base 10
How does it work correctly?

ValueError: invalid literal for int() with base 10: 'Oompa Loompa\x07\x08'

I have the TCP server set up for receiving messages from connected clients, but when the message contains packed hex e.g "Oompa Loompa\x07\x08" it shows me this error:
ValueError: invalid literal for int() with base 10: 'Oompa Loompa\x07\x08'
I guess I have decoding issue in the code but I don't know how to fix it.
import socket
import threading
HEADER = 64
PORT = 5050
SERVER = "192.168.1.103"
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "!DISCONNECT"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg == DISCONNECT_MESSAGE:
connected = False
print(f"[{addr}] {msg}")
conn.send("Msg received".encode(FORMAT))
conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[Active Clients] {threading.active_count() - 1}")
print("[BOOTING] server is starting...")
start()
It seems like hex is a strings and needs to be an int. Try sending that message in binary.

pymodbus does not read registers

I am developing a program to read Modbus data via serial RTU using pymodbus.
My purpose is to read data from an ABB XRCG4 Xseries flow computing PC. I know that the COM port on the device side is COM1 and the serial protocol is RS232, on my PC, using a serial converter I am trying to connect to it.
I know the configuration as follows:
PROTOCOL= 'rtu'
USB_PORT = 'COM4'
PARITY = 'None'
BAUD_RATE = 9600
TIMEOUT = 3
For test purposes I made an Arduino board into a Modbus Slave. I can read the data from the board with QModMaster, Modbus Pool and SimplyModbusMaster but I am unable to do so with my script. For the board I am unable to read anything at all, not eve with the programs mentioned above.
When I use the above mentioneds program to read data from the Arduino, everything works fine, when I try with my script, I get the AttributeError: 'ModbusIOException' object has no attribute 'registers'
I also noticed that I get this error if I unplug the cable while connection is running.
What am I missing? My guess is that I might not have a hardware dealer for the dsrdtr exchange, according to page 24 of the pymodbus documentation or maybe on the board side, the Register Format is not ok for my code.
Here you can see the details from the ABB board
Port description part1
Port description part2
My code:
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.client.sync import *
from pymodbus.register_read_message import *
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.compat import iteritems
from pymodbus.exceptions import *
import time
import logging
import logging.handlers as Handlers
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
USB_PORT = 'COM4'
PARITY = 'N' #'N'
BAUD_RATE = 9600
TIMEOUT = 0.15
client = ModbusClient(method='rtu',
port=USB_PORT,
stopbits=1,
bytesize=8,
parity=PARITY,
baudrate=BAUD_RATE,
timeout=TIMEOUT, )
while True:
connection = client.connect()
#print(client.)
print(f"COM Details {client.socket}")
#client.socket.setRTS(True)
print(f"Connection status is: {connection} \nClient State: {client.state} \nTimeout: {client.timeout}")
#print(client.get_serial_settings)
try:
#################################### CITIM INPUT REGISTER (adresa,nr de registrii si unit ID
input_value = client.read_input_registers(count=0x01,address=10,unit=0x01)
#client.socket.setRTS(False)
print(input_value)
decoder = BinaryPayloadDecoder.fromRegisters(input_value.registers, byteorder=Endian.Little)
decoded = {
'string': decoder.decode_string(8),
'float': decoder.decode_32bit_float(),
'16uint': decoder.decode_16bit_uint(),
'ignored': decoder.skip_bytes(2),
#'8int': decoder.decode_8bit_int(),
'bits': decoder.decode_bits(),}
############### CITIM HOLDING REGISTER (exemplu, modelul vantilatorului)
holding_values = client.read_holding_registers(0xD1A5,6,unit=0x01)
holding_decoder = BinaryPayloadDecoder.fromRegisters(holding_values.registers, byteorder=Endian.Big)
holding_decoded = {
'string': holding_decoder.decode_string(8),
#'float': holding_decoder.decode_32bit_float(),
#'16uint': holding_decoder.decode_16bit_uint(),
'ignored': holding_decoder.skip_bytes(2),
#'8int': holding_decoder.decode_8bit_int(),
'bits': holding_decoder.decode_bits(),
}
print("-" * 60)
print("INPUT REGISTERS:")
print("-" * 60)
print(f"\nResponse: {input_value.registers} \nInput Registers Decoded values: \n")
for name, value in iteritems(decoded):
print ("%s\t" % name, value)
print(f"\n Decoded speed: {decoded['float']}")
print(f"Holding values registers:\n {holding_values.registers}")
print("-" * 60)
print("Holding Values Decoded Data")
print("-" * 60)
for name, value in iteritems(holding_decoded):
print ("%s\t" % name, value)
except ConnectionException as e:
print(f"USB Disconnected {e}")
time.sleep(2)
client.close()

How to receive a message through TCPBasicClientApp in omnet++?

I have made two different TCP Applications in Omnet++, one is TCPBasicClientApp and other is TCPGenericServerApp. TCP client application is successfully sending a GenericAppMsg through TCP Protocol. Once the message is received on the Server Side (with a specific replyLength) it is sending it back to the client side through SendBack() method (also mentioned in the inet example application).
My question is, how to receive this message back on the client side?
Here is the omnet.ini file code, for this transfer,
The Client Side,
**.host[0].numTcpApps = 1
**.host[0].tcpApp[0].typename = "ReputationAlgorithmApplication"
**.host[0].tcpApp[0].localAddress = ""
**.host[0].tcpApp[0].localPort = -1
**.host[0].tcpApp[0].connectAddress = "host[3]"
**.host[0].tcpApp[0].connectPort = 2000
**.host[0].tcpApp[0].dataTransferMode = "object"
The Server Side,
**.host[3].numTcpApps = 1
**.host[3].tcpApp[*].typename = "ReputationServerApplication"
**.host[3].tcpApp[*].localAddress = "host[3]"
**.host[3].tcpApp[*].localPort = 2000
Here is the sendBack method on Server Side,
void ReputationServerApplication::sendBack(cMessage *msg) {
cPacket *packet = dynamic_cast<cPacket *>(msg);
if (packet) {
msgsSent++;
bytesSent += packet->getByteLength();
emit(sentPkSignal, packet);
EV_INFO << "sending \"" << packet->getName() << "\" to TCP, "
<< packet->getByteLength() << " bytes\n";
} else {
EV_INFO << "sending \"" << msg->getName() << "\" to TCP\n";
}
DummyMessageForReputation *msgDum =
dynamic_cast<DummyMessageForReputation *>(msg);
std::cout << "\n Tested: Message with the string "
<< msgDum->getMessageString() << " is sending back to "
<< msgDum->getNodeName();
send(msgDum, "tcpOut");
}
Any help would be appreciated.
You can use TCPBasicClientApp::socketDataArrived() to process the received message on the client side.

iOS UDP broadcast vs. PHP UDP broadcast

I'm trying to send data via UDP to the network. I've got some PHP code running on my local machine which works:
#!/usr/bin/php -q
<?php
$socket = stream_socket_client('udp://225.0.0.0:50000');
for($i=0;$i<strlen($argv[1]);$i++) $b.="\0\0\0".$argv[1][$i];
fwrite($socket,$b,strlen($argv[1])*4);
fclose($socket);
?>
Gives me the output in tcpdump:
18:53:24.504447 IP 10.0.1.2.52919 > 225.0.0.0.50000: UDP, length 36
I'm trying to get to the same result on a remote iOS with the following code:
- (void)broadcast:(NSString *)dx {
NSData* data=[dx dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"Broadcasting data: %#", dx);
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr4client;
memset(&addr4client, 0, sizeof(addr4client));
addr4client.sin_len = sizeof(addr4client);
addr4client.sin_family = AF_INET;
addr4client.sin_port = htons(PORT);
addr4client.sin_addr.s_addr = htonl(INADDR_BROADCAST);
int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void *)&yes, sizeof(yes)) == -1) {
NSLog([NSString stringWithFormat:#"Failure to set broadcast! : %d", errno]);
}
char *toSend = (char *)[data bytes];
if (sendto(fd, toSend, [data length], 0, (struct sockaddr *)&addr4client, sizeof(addr4client)) == -1) {
NSLog([NSString stringWithFormat:#"Failure to send! : %d", errno]);
}
close(fd);
}
Which gives me the following output in tcpdump:
19:01:22.776192 IP 10.0.1.4.60643 > broadcasthost.50000: UDP, length 9
Looks basically OK, but doesn't arrive in Quartz Composer for some reason, I guess there should be the IP address or something instead of 'broadcasthost'.
Any idea?
The problem was not in the implementation of the broadcaster, but the format of the string. To work with Quartz Composer, every character needs to be preceded by a backslash-zero combination: "\0\0\0", so "abc" has to be formatted and sent as "\0\0\0a\0\0\0b\0\0\0c".
See also Celso Martinho's blog article: Leopard’s Quartz Composer and Network events.
I suggest using AsyncSocket ( google it, its on googlecode ), very well tested objective-c code that runs on iOS.
That way you can send data really easy using a NSData object. AsyncSocket manages the hard part for you.
If that isn't an option for you you should use CFSocket. What you are doing is implementing code that has been written for you already, CFSocket.

Resources