How to decode payload from modbus using NodeJS? - node.js

I have a schneider power meter with rs485 surport. I using python with pymodbus to read register and decode payload from it (success). But now I want to do this with NodeJS, I can get raw data but I dont know how to decode it, I tried some method but result wrong!
This my python code:
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
def validator(instance):
if not instance.isError():
'''.isError() implemented in pymodbus 1.4.0 and above.'''
decoder = BinaryPayloadDecoder.fromRegisters(
instance.registers,
byteorder=Endian.Big, wordorder=Endian.Little
)
return float(decoder.decode_32bit_float())
else:
# Error handling.
return None
validator([5658, 17242]) # Result is 218.1
When I use NodeJS it return buffer and i tried to decode with:
let buf = Buffer.from([0xd6, 0xd4, 0x42, 0x47]);
payload = buf.readFloatBE(0); // It return other float number not 218.1
Can everyone help me ! Thanks !

Related

pyserial response unicodeDecodeError

import serial
s = serial.Serial(port = 'Com3', 9600, timeout = 2)
data = s.readline().decode().rstrip("\r\n")
So basically when I try to read the data I get the error.
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfb in position 20: invalid start byte
From the documentation of the instrument I am trying to communicate with. the data is in the form:
..ss3422/34/54--1.8E+03<,>…..0.7E+03<,...1.71E-09<,<√.<*.<
I was able to fix the problem by changing to encoding = "ISO-8859-1".

why in the raw data the first byte is in asciii

I've got the followings raw data in bytes :
b'\r\xdc\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b'\x16\xd9\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\xf2d\x02\x00\x97\x00'
b'K\xde\xc9\x01\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b':\xda\xc9\x02\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b'B\xda\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b'\x15\xdb\xc9\x01\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
As you can see the first value is in ascii. For example this couple are the same:
b'B\xda\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
Looking into the code of pyshark i see this :
def get_raw_packet(self):
assert "FRAME_RAW" in self, "Packet contains no raw data. In order to contains it, " \
"make sure that use_json and include_raw are set to True " \
"in the Capture object"
raw_packet = b''
byte_values = [''.join(x) for x in zip(self.frame_raw.value[0::2], self.frame_raw.value[1::2])]
for value in byte_values:
raw_packet += binascii.unhexlify(value)
return raw_packet
And my code is the following :
import pyshark
from pyshark.capture.pipe_capture import PipeCapture
import os
FIFO = 'informacion.pcap'
def print_callback(pkt):
print (pkt.get_raw_packet())
with open(FIFO) as fifo:
capture = PipeCapture(pipe=fifo,use_json=True,include_raw=True)
capture.apply_on_packets(print_callback)

I can't seem to make the google.cloud.texttospeech to work

Im using Python 3.8 and i copy pasted this code as a test.
from google.cloud import texttospeech
# Instantiates a client
client = texttospeech.TextToSpeechClient()
# Set the text input to be synthesized
synthesis_input = texttospeech.SynthesisInput(text="Hello, World!")
# Build the voice request, select the language code ("en-US") and the ssml
# voice gender ("neutral")
voice = texttospeech.VoiceSelectionParams(
language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL
)
# Select the type of audio file you want returned
audio_config = texttospeech.AudioConfig(
audio_encoding=texttospeech.AudioEncoding.MP3
)
# Perform the text-to-speech request on the text input with the selected
# voice parameters and audio file type
response = client.synthesize_speech(
input=synthesis_input, voice=voice, audio_config=audio_config
)
# The response's audio_content is binary.
with open("output.mp3", "wb") as out:
# Write the response to the output file.
out.write(response.audio_content)
print('Audio content written to file "output.mp3"')
This is the code that is shown by google as can be seen here : GOOGLE LINK
Now my problem is that i get this error
PS C:\Users\User\Desktop> & C:/Users/User/AppData/Local/Programs/Python/Python38/python.exe "c:/Users/User/Desktop/from google.cloud import texttospeech.py"
Traceback (most recent call last):
File "c:/Users/User/Desktop/from google.cloud import texttospeech.py", line 7, in <module>
synthesis_input = texttospeech.types.SynthesisInput(text="Hello, World!")
AttributeError: module 'google.cloud.texttospeech' has no attribute 'types'
PS C:\Users\User\Desktop>
I tried changeing this to add the credentials inside the code but the problem persists.
This is the line i changed:
client = texttospeech.TextToSpeechClient(credentials="VoiceAutomated-239f1c05600c.json")
I could solve this error by downgrading the library:
pip3 install "google-cloud-texttospeech<2.0.0"
I got the same error when running that script, i checked the source code and the interface has changed, basically you need to delete all "enums" and "types". It will look similar to this:
# Instantiates a client
client = texttospeech.TextToSpeechClient()
# Set the text input to be synthesized
synthesis_input = texttospeech.SynthesisInput(text="Hello, World!")
# Build the voice request, select the language code ("en-US") and the ssml
# voice gender ("neutral")
voice = texttospeech.VoiceSelectionParams(
language_code='en-US',
ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL)
# Select the type of audio file you want returned
audio_config = texttospeech.AudioConfig(
audio_encoding=texttospeech.AudioEncoding.MP3)
# Perform the text-to-speech request on the text input with the selected
# voice parameters and audio file type
response = client.synthesize_speech(input=synthesis_input, voice=voice, audio_config=audio_config)
# The response's audio_content is binary.
with open('output.mp3', 'wb') as out:
# Write the response to the output file.
out.write(response.audio_content)
print('Audio content written to file "output.mp3"')
I debug the code and to get it to work i had to write enums and types when needed. Taking the text to speech google documentation example and including some little adjusments:
"""Synthesizes speech from the input string of text or ssml.
Note: ssml must be well-formed according to:
https://www.w3.org/TR/speech-synthesis/
"""
from google.cloud import texttospeech
import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "./config/credentials.json"
# Instantiates a client
client = texttospeech.TextToSpeechClient()
# Set the text input to be synthesized
synthesis_input = texttospeech.types.SynthesisInput(text="Hello, World!")
# Build the voice request, select the language code ("en-US") and the ssml
# voice gender ("neutral")
voice = texttospeech.types.VoiceSelectionParams(
language_code="en-US", ssml_gender=texttospeech.enums.SsmlVoiceGender.NEUTRAL
)
# Select the type of audio file you want returned
audio_config = texttospeech.types.AudioConfig(
audio_encoding=texttospeech.enums.AudioEncoding.MP3
)
# Perform the text-to-speech request on the text input with the selected
# voice parameters and audio file type
response = client.synthesize_speech(
input_=synthesis_input, voice=voice, audio_config=audio_config
)
# The response's audio_content is binary.
with open("./output_tts/output.mp3", "wb") as out:
# Write the response to the output file.
out.write(response.audio_content)
print('Audio content written to file "output.mp3"')
hope this works for you
It will work Python 3.6 but it won't work with Python 3.7 with latest update of google-cloud-texttospeech. If you want us it with Python 3.7 Try the below code.
from google.cloud import texttospeech
def foo():
client = texttospeech.TextToSpeechClient(credentials=your_google_creds_here)
translated_text = Text
synthesis_input = texttospeech.types.SynthesisInput(text=translated_text)
pitch = 1
speaking_rate = 1
lang_code = 'en-us' # your_lang_code_hear
gender = 'male'
gender_data = {
'NEUTRAL': texttospeech.enums.SsmlVoiceGender.NEUTRAL,
'FEMALE': texttospeech.enums.SsmlVoiceGender.FEMALE,
'MALE': texttospeech.enums.SsmlVoiceGender.MALE
}
voice = texttospeech.types.VoiceSelectionParams(language_code=lang_code, ssml_gender=gender_data[gender.upper()])
audio_config = texttospeech.types.AudioConfig(
audio_encoding=texttospeech.enums.AudioEncoding.MP3, speaking_rate=float(speaking_rate), pitch=float(pitch)
)
print('Voice config and Audio config : ', voice, audio_config)
response = client.synthesize_speech(
synthesis_input, voice, audio_config)
You need to migrate to version 2.0 visit the site below for details on the changes you need to make since you most likely followed a tutorial using an older version of texttospeech:
https://googleapis.dev/python/texttospeech/2.0.0/UPGRADING.html
I will also include an example using the beta version of 2.0.0.
import google.cloud.texttospeech_v1beta1 as ts
import time
nm = "en-US-Wavenet-I"
hz = 48000
def useTextToSpeech(speaking, lang, speed,stinger):
client = ts.TextToSpeechClient()
synthesis_input = ts.SynthesisInput(text=speaking)
voice = ts.VoiceSelectionParams(
language_code=lang,
ssml_gender=ts.SsmlVoiceGender.MALE,
name=nm,
)
audio_config = ts.AudioConfig(
audio_encoding=ts.AudioEncoding.OGG_OPUS,
speaking_rate=speed,
pitch = 1.2,
sample_rate_hertz=hz,
effects_profile_id=['headphone-class-device' ],
)
response = client.synthesize_speech(
request={
"input": synthesis_input,
"voice":voice,
"audio_config":audio_config
}
)
with open((stinger+'.opus'), 'wb') as out:
out.write(response.audio_content)
print('Audio content written to file as "'+stinger+'.opus"')
from playsound import playsound
import os
#playsound(os.path.abspath((stinger+'.opus')))
output = str("Make sure when you follow tutorials they are using the most up to date version of the Api!")
useTextToSpeech(output, "en-US-Wavenet-I",1.0,("example"+str(1)))

Converting arduino serial readings into float or int on the raspberry pi with python3

I have a serial connection between my raspberry pi and my arduino. I can send data from arduino to the pi but when I try to convert the receiving data into a int or a float I get an error message.
Let's say I try to send the number 35 to the pi, and try to convert it on the python side I get following message:
invalid literal for int() with base 10:''
and when I try to convert it to float I get the following message:
could not convert string to float.
I'm using Idle 3.5.3 on the raspberry pi. I tried many things I've seen in this forum: like strip() but nothing seems to work. What could be wrong?
Arduino Code:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(35);
delay(5000);
}
Python Code:
#!/usr/bin/env python3
import time
import serial
from array import array
import csv
arduino = serial.Serial(
port='/dev/ttyACM0',
baudrate = 9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1
)
arduino.flushInput()
print("test")
while 1:
incoming = arduino.readline().decode('ascii').strip()
float(incoming)
print(incoming)
I expected a cast to int or float but I get only error messages
I got it.
incoming = arduino.readline().decode('ascii')
if not incoming is "":
if int(incoming.strip()) == 1:
data.append(float(arduino.readline().decode('ascii').strip())/100)

Decoding error while decoding stdout from subprocess.Popen

string.decode() throws an error, when i try to decode the line output of an stdout.PIPE. The error message is:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x84 in position 8: invalid start byte
0x84 should be the letter 'ä'. The line that fails reads as follows:
b' Datentr\x84ger in Laufwerk C: ist System'
I can't nail it down. I already checked the encoding using sys.stdout.encoding, which is utf-8.
import subprocess
import re
prc = subprocess.Popen(["cmd.exe"], shell = False, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
prc.stdin.write(b"dir\n")
outp, inp = prc.communicate()
regex = re.compile(r"^.*(\d\d:\d\d).*$")
for line in outp.splitlines():
match = regex.match(line.decode('utf-8'))# <--- decode fails here.
if match:
print(match.groups())
prc.stdin.close()
CMD encodes text using ISO-8859-15. So the text that comes through the PIPE needs to be decoded using ISO, even if python encodes the stdout using utf-8.
If you don’t know the encoding, the cleanest way to solve this is to specify the errors param of bytearray.decode, e.g.:
import subprocess
p = subprocess.run(['echo', b'Evil byte: \xe2'], stdout=subprocess.PIPE)
p.stdout.decode(errors='backslashreplace')
Output:
'Evil byte: \\xe2\n'
The list of possible values can be found here:
https://docs.python.org/3/library/codecs.html#codecs.register_error

Resources