Python NMEA GNSS Cold Start command - python

On my hardware, I translate the usb port to com using the usb_transit_on internal command.
After that, I connect to the port using the program and when I enter this command "b5 62 06 04 04 00 ff ff 00 00 0c 5d"
I perform a cold restart and note the time spent by the satellites, the task is to do the same only without the program, the question is whether it is possible how then send command "b5 62 06 04 04 00 ff ff 00 00 0c 5d" or "$PMTK103*30"
With Python, I tried but nothing happened.
import time
import pynmea2
import serial
import csv
import io
def status():
# ser = serial.Serial('COM12')
ser = serial.Serial(
port = "COM12",
baudrate = 9600,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE
)
print("Waiting for data")
ser.write(b"b5 62 06 04 04 00 ff ff 00 00 0c 5d")
while True:
message = ser.readline().decode()
message = message.strip()
if "$GNRMC" in message:
gnrmc = pynmea2.parse(message)
gnrmc_status = gnrmc.status
return gnrmc_status
else:
continue
print(status())
I thought with this command you can send a message to the GNSS module

Related

Encoding Spyne SOAP XML response with Latin-1

I recently set up a Spyne application for sending an XML response. As it stands now, the application is correctly sending the response -- however, it is currently sending a UTF-8 encoded document. I would like to instead send the document as Latin-1 (iso-8859-1) encoded.
I've tried to use the "encoding=" argument, but it seems to have no effect on the response beyond changing the header.
Below is the code for my application:
import logging
from spyne import Application, rpc, ServiceBase, Integer, Unicode, AnyDict
from spyne import Iterable
from spyne.protocol.soap import Soap11
from spyne.protocol.xml import XmlDocument
from spyne.server.wsgi import WsgiApplication
class CoreService(ServiceBase):
#rpc(Unicode, Unicode, Integer, Integer, _returns=AnyDict) ##rpc arguments corespond to the retrieve_score() arguments below
def retreive_score(ctx):
return score # This is a dictionary
application = Application([CoreService], 'spyne.iefp.soap',
in_protocol=Soap11(validator='lxml'),
out_protocol=XmlDocument(polymorphic=True, encoding='iso-8859-1'))
wsgi_application = WsgiApplication(application)
if __name__ == '__main__':
import logging
from wsgiref.simple_server import make_server
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
logging.info("listening on port 8000")
logging.info("wsdl is at: http://10.10.28.84:8000/?wsdl")
server = make_server('0.0.0.0', 8000, wsgi_application)
server.serve_forever()
I fixed (and switched to HttpRpc for input as I didn't have a SOAP client handy) and ran your code. It works for me.
import logging
from spyne import Application, rpc, ServiceBase, Integer, Unicode, AnyDict
from spyne import Iterable
from spyne.protocol.soap import Soap11
from spyne.protocol.http import HttpRpc
from spyne.protocol.xml import XmlDocument
from spyne.server.wsgi import WsgiApplication
class CoreService(ServiceBase):
#rpc(Unicode, Unicode, Integer, Integer, _returns=AnyDict)
def retrieve_score(ctx, s1, s2, i1, i2):
return {'rain': u'yağmur'} # This is a dictionary
application = Application([CoreService], 'spyne.iefp.soap',
in_protocol=HttpRpc(),
out_protocol=XmlDocument(polymorphic=True, encoding='iso-8859-9'))
wsgi_application = WsgiApplication(application)
if __name__ == '__main__':
import logging
from wsgiref.simple_server import make_server
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
logging.info("listening on port 8000")
logging.info("wsdl is at: http://127.0.0.1:8000/?wsdl")
server = make_server('0.0.0.0', 8000, wsgi_application)
server.serve_forever()
The excerpt from curl -s localhost:8000/retrieve_score | hexdump -C is:
00000070 65 5f 73 63 6f 72 65 52 65 73 75 6c 74 3e 3c 72 |e_scoreResult><r|
00000080 61 69 6e 3e 79 61 f0 6d 75 72 3c 2f 72 61 69 6e |ain>ya.mur</rain|
00000090 3e 3c 2f 6e 73 30 3a 72 65 74 72 69 65 76 65 5f |></ns0:retrieve_|
Where you have 0xF0 for 'ğ', which is correct, according to: https://en.wikipedia.org/wiki/ISO/IEC_8859-9

Can't connect to modbus RTU over TCP. What is wrong?

Prove that device is working: ./modpoll -m enc -p4660 -t4:float -r60 -a3 192.168.1.1:
Protocol configuration: Encapsulated RTU over TCP
Slave configuration...: address = 3, start reference = 60, count = 1
Communication.........: 192.168.1.1, port 4660, t/o 1.00 s, poll rate 1000 ms
Data type.............: 32-bit float, output (holding) register table
TRACELOG: Set poll delay 0
TRACELOG: Set port 4660
TRACELOG: Open connection to 192.168.1.1
TRACELOG: Configuration: 1000, 1000, 0
-- Polling slave... (Ctrl-C to stop)
TRACELOG: Read multiple floats 3 60
TRACELOG: Send(6): 03 03 00 3B 00 02
TRACELOG: Recv(9): 03 03 04 6E 08 42 F7 35 FF
[60]: 123.714905
And how I try to get the connection with pymodbus library:
from pymodbus.client.sync import ModbusTcpClient
from pymodbus.transaction import ModbusRtuFramer
ModbusTcpClient(host='192.168.1.1', port=4660, framer=ModbusRtuFramer, timeout=5)
client.connect() # returns True
client.read_holding_registers(60, count=3, unit=0x03)
And get this result:
pymodbus.exceptions.ConnectionException: Modbus Error: [Connection] 192.168.1.1:4660
Modbus Error: [Connection] 192.168.1.1:4660
What I'm doing wrong?

ZMQ: No subscription message on XPUB socket for multiple subscribers (Last Value Caching pattern)

I implemented the Last Value Caching (LVC) example of ZMQ (http://zguide.zeromq.org/php:chapter5#Last-Value-Caching), but can't get a 2nd subscriber to register at the backend.
The first time a subscriber comes on board, the event[0] == b'\x01' condition is met and the cached value is sent, but the second subscriber (same topic) doesn't even register (if backend in events: is never true). Everything else works fine. Data gets passed from the publisher to the subscribers (all).
What could be the reason for this? Is the way the backend is connected correct? Is this pattern only supposed to work with the first subscriber?
Update
When I subscribe the 2nd subscriber to another topic, I get the right behaviour (i.e. \x01 when subscribing). This really seems to work for the first subscriber onlt . Is is a bug in ZeroMQ?
Update 2
Here's a minimal working example that shows that the LVC pattern is not working (at least not the way it's implemented here).
# subscriber.py
import zmq
def main():
ctx = zmq.Context.instance()
sub = ctx.socket(zmq.SUB)
sub.connect("tcp://127.0.0.1:5558")
# Subscribe to every single topic from publisher
print 'subscribing (sub side)'
sub.setsockopt(zmq.SUBSCRIBE, b"my-topic")
poller = zmq.Poller()
poller.register(sub, zmq.POLLIN)
while True:
try:
events = dict(poller.poll(1000))
except KeyboardInterrupt:
print("interrupted")
break
# Any new topic data we cache and then forward
if sub in events:
msg = sub.recv_multipart()
topic, current = msg
print 'received %s on topic %s' % (current, topic)
if __name__ == '__main__':
main()
And here's the broker (as in the example, but with a bit more verbosity and an integrated publisher).
# broker.py
# from http://zguide.zeromq.org/py:lvcache
import zmq
import threading
import time
class Publisher(threading.Thread):
def __init__(self):
super(Publisher, self).__init__()
def run(self):
time.sleep(10)
ctx = zmq.Context.instance()
pub = ctx.socket(zmq.PUB)
pub.connect("tcp://127.0.0.1:5557")
cnt = 0
while True:
msg = 'hello %d' % cnt
print 'publisher is publishing %s' % msg
pub.send_multipart(['my-topic', msg])
cnt += 1
time.sleep(5)
def main():
ctx = zmq.Context.instance()
frontend = ctx.socket(zmq.SUB)
frontend.bind("tcp://*:5557")
backend = ctx.socket(zmq.XPUB)
backend.bind("tcp://*:5558")
# Subscribe to every single topic from publisher
frontend.setsockopt(zmq.SUBSCRIBE, b"")
# Store last instance of each topic in a cache
cache = {}
# We route topic updates from frontend to backend, and
# we handle subscriptions by sending whatever we cached,
# if anything:
poller = zmq.Poller()
poller.register(frontend, zmq.POLLIN)
poller.register(backend, zmq.POLLIN)
# launch a publisher
p = Publisher()
p.daemon = True
p.start()
while True:
try:
events = dict(poller.poll(1000))
except KeyboardInterrupt:
print("interrupted")
break
# Any new topic data we cache and then forward
if frontend in events:
msg = frontend.recv_multipart()
topic, current = msg
cache[topic] = current
backend.send_multipart(msg)
### this is where it fails for the 2nd subscriber.
### There's never even an event from the backend
### in events when the 2nd subscriber is subscribing.
# When we get a new subscription we pull data from the cache:
if backend in events:
print 'message from subscriber'
event = backend.recv()
# Event is one byte 0=unsub or 1=sub, followed by topic
if event[0] == b'\x01':
topic = event[1:]
print ' => subscribe to %s' % topic
if topic in cache:
print ("Sending cached topic %s" % topic)
backend.send_multipart([ topic, cache[topic] ])
elif event[0] == b'\x00':
topic = event[1:]
print ' => unsubscribe from %s' % topic
if __name__ == '__main__':
main()
Running this code (1 x broker.py, 2 x subscriber.py) shows that the first subscriber registers at the broker as expected (\x01 and cache lookup), but the 2nd subscriber does not get registered the same way. Interestingly, the 2nd subscriber is hooked up to the pub/sub channel, as after a while (10 sec) both subscribers receive data from the publisher.
This is very strange. Perhaps some of my libraries are outdated. Here's what I got:
Python 2.7.9 (v2.7.9:648dcafa7e5f, Dec 10 2014, 10:10:46)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import zmq
>>> zmq.__version__
'14.1.1'
$ brew info zeromq
zeromq: stable 4.0.5 (bottled), HEAD
High-performance, asynchronous messaging library
http://www.zeromq.org/
/usr/local/Cellar/zeromq/4.0.5_2 (64 files, 2.8M) *
Poured from bottle
From: https://github.com/Homebrew/homebrew/blob/master/Library/Formula/zeromq.rb
==> Dependencies
Build: pkg-config ✔
Optional: libpgm ✘, libsodium ✘
Update 3
This behaviour can also be observed in zeromq 4.1.2 and pyzmq-14.7.0 (with or without libpgm and libsodium installed).
Update 4
Another observation suggests that the first subscriber is somehow handled differently: The first subscriber is the only one unsubscribing in the expected way from the XPUB socket (backend) by preceding its subscription topic with \x00. The other subscribers (I tried more than 2) stayed mute on the backend channel (although receiving messages).
Update 5
I hope I'm not going down a rabbit hole, but I've looked into the czmq bindings and ran my Python example in C. The results are the same, so I guess it's not a problem with the bindings, but with libzmq.
I also verified that the 2nd subscriber is sending a subscribe message and indeed I can see this on the wire:
First subscribe:
0000 02 00 00 00 45 00 00 3f 98 be 40 00 40 06 00 00 ....E..? ..#.#...
0010 7f 00 00 01 7f 00 00 01 fa e5 15 b6 34 f0 51 c3 ........ ....4.Q.
0020 05 e4 8b 77 80 18 31 d4 fe 33 00 00 01 01 08 0a ...w..1. .3......
0030 2a aa d1 d2 2a aa cd e9 00 09 01 6d 79 2d 74 6f *...*... ...my-to
0040 70 69 63 pic
2nd subscribe message with difference (to above) marked and explained. The same data is sent in the subscribe frame.
identification
v
0000 02 00 00 00 45 00 00 3f ed be 40 00 40 06 00 00 ....E..? ..#.#...
src port sequence number
v v v v v
0010 7f 00 00 01 7f 00 00 01 fa e6 15 b6 17 da 02 e7 ........ ........
Acknowledgement number window scaling factor
v v v v v
0020 71 4b 33 e6 80 18 31 d5 fe 33 00 00 01 01 08 0a qK3...1. .3......
timestamp value timestamp echo reply
v v v |<-------- data -------
0030 2a aa f8 2c 2a aa f4 45 00 09 01 6d 79 2d 74 6f *..,*..E ...my-to
------>|
0040 70 69 63 pic
I found the solution for this problem, and even though I read the docs front to back and back to front, I had not seen it. The key is XPUB_VERBOSE. Add this line to after the backend initialisation and everything works fine
backend.setsockopt(zmq.XPUB_VERBOSE, True)
Here's an extract from the official documentation:
ZMQ_XPUB_VERBOSE: provide all subscription messages on XPUB sockets
Sets the XPUB socket behavior on new subscriptions and
unsubscriptions. A value of 0 is the default and passes only new
subscription messages to upstream. A value of 1 passes all
subscription messages upstream.
Option value type int Option value unit 0, 1 Default value 0
Applicable socket types ZMQ_XPUB
Pieter Hintjens has some more information on this in his blog. This is the relevant section:
A few months ago we added a neat little option (ZMQ_XPUB_VERBOSE) to
XPUB sockets that disables its filtering of duplicate subscriptions.
This now works for any number of subscribers. We use this as follows:
void *publisher = zsocket_new (ctx, ZMQ_XPUB);
zsocket_set_xpub_verbose (publisher, 1);
zsocket_bind (publisher, "tcp://*:6001");
The LVC pattern description should be updated to reflect this setting, as this pattern won't work otherwise.

PySerial has problems reading Arduino

I want to dump a ROM. The Arduino waits until it receives the key which is one digit. I use this digit as the starting command and as a parameter to tell the Arduino how big the ROM is. This is my Arduino code (simplified for testing):
void setup() {
Serial.begin(115200);
}
void loop() {
uint8_t key = 10;
while(key > 2){
key = Serial.read();
key -= '0';
}
Serial.print("75 A E8 98 D4 E8 8A E4 E8 EB E4 F9 C3 60 3C 55");
Serial.println("");
Serial.print("74 C E8 35 3 E8 79 E1 88 96 9F 0 EB F E8");
Serial.println("");
Serial.print("0 E8 9 1 FF 76 19 E8 4F DC 8F 46 19 61 F8 C3");
Serial.println("");
Serial.print("E8 5E E1 33 C0 EB 29 B8 1 0 81 BE A0 0 0 51");
Serial.println("");
Serial.println("EOF");
}
And this is my Python code to tell the Arduino to start dumping and to read the response:
line = " "
ser = serial.Serial("COM10", 115200, timeout=1)
ser.write("1")
ser.flush()
while line != "EOF":
line = ser.readline().strip
print line
ser.close()
The problem: its printing nothing.
PS: already tried different values for timeout but neither 0 or None worked.
EDIT: Everyone else is invited to awnser! I'm using Python 2.7.6 - Anaconda 1.9.2 32bit # Win7x64
EDIT2 The solution is to add a delay of 2secs (time.speep(2)) before the first write in python. More details here: pySerial works fine in Python interpreter, but not standalone
Pyserial certainly has no problem reading arduino serial ... I have done it many many times
try this
ser = serial.Serial("COM10", 115200, timeout=5)
ser.flush()
ser.write("1")
print ser.read(1000)
ser.close()
or abstract it further
class MySerial:
def __init__(self,*args,**kwargs):
kwargs["timeout"] = kwargs.get("timeout",5) #ensure timeout set
self.ser = serial.Serial(*args,**kwargs)
def query(self,cmd):
self.ser.flush()
self.ser.write(cmd)
return self.ser.read(100000)
ser = MySerial("COM10", 115200, timeout=5)
print ser.query("1")
also I am a little curious why you are writing hex to a string all space separated like that instead of just writing in bytes...
you can verify that you can get reads as follows
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.read();
Serial.println("Hello World!\r");
}
this will wait for anything then send the hello world string ... make sure you see that at least then continue tweaking it to behave as you want (EG. get a specific value from the read before continuing ,send a message other than hello world ... my guess is that its not getting past your Serial.read() for whatever reason

How to test for hexidecimal output on serial port in python

When i send a command over serial, the slave responds with a hexidecimal sequence, i.e.:
this series:
05 06 40 00 02 05 F6 5C
gives me
05 07 40 05 02 05 71 37 FF
The response always ends with the FF byte. So i want to read the bytes into a buffer untill i encounter FF. Than the buffer should be printed and the function should return.
import serial
s_port = 'COM1'
b_rate = 2400
#method for reading incoming bytes on serial
def read_serial(ser):
buf = ''
while True:
inp = ser.read(size=1) #read a byte
print inp.encode("hex") #gives me the correct bytes, each on a newline
buf = buf + inp #accumalate the response
if 0xff == inp.encode("hex"): #if the incoming byte is 0xff
print inp.encode("hex") # never here
break
return buf
#open serial
ser = serial.Serial(
port=s_port,
baudrate=b_rate,
timeout=0.1
)
while True:
command = '\x05\x06\x40\x00\x02\x05\xF6\x5C' #should come from user input
print "TX: "
ser.write(command)
rx = read_serial(ser)
print "RX: " + str(rx)
gives me:
TX:
05
07
40
05
02
05
71
37
ff
Why is the condition never met?
It's because you're comparing apples and oranges. inp.encode("hex") returns a string. Let's say you read the letter "A". "A".encode("hex") returns the string "41" and 0x41 != "41". You should either do:
if '\xff' == inp:
....
Or, convert inp into a number using ord():
if 0xff == ord(inp):
....
Then it should work as expected.

Categories

Resources