-
-
Notifications
You must be signed in to change notification settings - Fork 317
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
extend output array with new types of data (#633)
* update the format to add new sensors Signed-off-by: Andrey Parfenov <a1994ndrey@gmail.com>
- Loading branch information
1 parent
b7e4dca
commit 4870729
Showing
19 changed files
with
1,915 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import enum | ||
import logging | ||
import random | ||
import socket | ||
import struct | ||
import time | ||
|
||
|
||
class State(enum.Enum): | ||
wait = 'wait' | ||
stream = 'stream' | ||
|
||
|
||
class Message(enum.Enum): | ||
start_stream = b'b' | ||
stop_stream = b's' | ||
ack_values = (b'd', b'~6', b'~5', b'o', b'F0') | ||
ack_from_device = b'A' | ||
time_calc_command = b'F4444444' | ||
|
||
|
||
class GaleaEmulator(object): | ||
|
||
def __init__(self): | ||
self.local_ip = '127.0.0.1' | ||
self.local_port = 2390 | ||
self.server_socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) | ||
self.server_socket.settimeout( | ||
0.1) # decreases sampling rate significantly because it will wait for recv 0.1 sec but it's just a test | ||
self.server_socket.bind((self.local_ip, self.local_port)) | ||
self.state = State.wait.value | ||
self.addr = None | ||
self.package_num = 0 | ||
self.transaction_size = 12 | ||
self.package_size = 114 | ||
|
||
def run(self): | ||
start_time = time.time() | ||
while True: | ||
try: | ||
msg, self.addr = self.server_socket.recvfrom(128) | ||
if msg == Message.start_stream.value: | ||
self.state = State.stream.value | ||
elif msg == Message.stop_stream.value: | ||
self.state = State.wait.value | ||
elif msg in Message.ack_values.value or msg.decode('utf-8').startswith('x'): | ||
self.server_socket.sendto(Message.ack_from_device.value, self.addr) | ||
elif msg == Message.time_calc_command.value: | ||
cur_time = time.time() | ||
resp = bytearray(struct.pack('d', (cur_time - start_time) * 1000)) | ||
self.server_socket.sendto(resp, self.addr) | ||
else: | ||
if msg: | ||
# we dont handle board config characters because they dont change package format | ||
logging.warn('received unexpected string %s', str(msg)) | ||
except socket.timeout: | ||
logging.debug('timeout for recv') | ||
|
||
if self.state == State.stream.value: | ||
transaction = list() | ||
for _ in range(self.transaction_size): | ||
single_package = list() | ||
for i in range(self.package_size): | ||
single_package.append(random.randint(0, 255)) | ||
single_package[0] = self.package_num | ||
|
||
cur_time = time.time() | ||
timestamp = bytearray(struct.pack('d', (cur_time - start_time) * 1000)) | ||
eda = bytearray(struct.pack('f', random.random())) | ||
ppg_red = bytearray(struct.pack('i', int(random.random() * 5000))) | ||
ppg_ir = bytearray(struct.pack('i', int(random.random() * 5000))) | ||
|
||
for i in range(88, 96): | ||
single_package[i] = timestamp[i - 88] | ||
for i in range(1, 5): | ||
single_package[i] = eda[i - 1] | ||
for i in range(84, 88): | ||
single_package[i] = ppg_ir[i - 84] | ||
for i in range(80, 84): | ||
single_package[i] = ppg_red[i - 80] | ||
single_package[77] = random.randint(0, 100) | ||
|
||
self.package_num = self.package_num + 1 | ||
if self.package_num % 256 == 0: | ||
self.package_num = 0 | ||
transaction.append(single_package) | ||
try: | ||
package = list() | ||
for i in range(self.transaction_size): | ||
package.extend(bytes(transaction[i])) | ||
self.server_socket.sendto(bytes(package), self.addr) | ||
except socket.timeout: | ||
logging.info('timeout for send') | ||
|
||
|
||
def main(): | ||
emulator = GaleaEmulator() | ||
emulator.run() | ||
|
||
|
||
if __name__ == '__main__': | ||
logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s', level=logging.INFO) | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
import logging | ||
import os | ||
import random | ||
import struct | ||
import subprocess | ||
import threading | ||
import time | ||
|
||
import pkg_resources | ||
from serial import Serial | ||
|
||
|
||
def write(port, data): | ||
return port.write(data) | ||
|
||
|
||
def read(port, num_bytes): | ||
return port.read(num_bytes) | ||
|
||
|
||
def get_isntaller(): | ||
return pkg_resources.resource_filename(__name__, os.path.join('com0com', 'setup_com0com_W7_x64_signed.exe')) | ||
|
||
|
||
def install_com0com(): | ||
this_directory = os.path.abspath(os.path.dirname(__file__)) | ||
directory = os.path.join(this_directory, 'com0com') | ||
if not os.path.exists(directory): | ||
os.makedirs(directory) | ||
cmds = [get_isntaller(), '/NCRC', '/S', '/D=%s' % directory] | ||
logging.info('running %s' % ' '.join(cmds)) | ||
p = subprocess.Popen(cmds, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
out, err = p.communicate() | ||
if p.returncode != 0: | ||
logging.error('stdout is %s' % out) | ||
logging.error('stderr is %s' % err) | ||
raise Exception('com0com installation failure') | ||
logging.info('Sleeping a few second, it doesnt work in appveyour without it') | ||
time.sleep(10) | ||
return directory | ||
|
||
|
||
def get_ports_windows(): | ||
directory = install_com0com() | ||
# remove ports from previous run if any | ||
p = subprocess.Popen([os.path.join(directory, 'setupc.exe'), 'remove', '0'], | ||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=directory) | ||
stdout, stderr = p.communicate() | ||
logging.info('remove stdout is %s' % stdout) | ||
logging.info('remove stderr is %s' % stderr) | ||
|
||
m_name = 'COM16' | ||
s_name = 'COM17' | ||
|
||
p = subprocess.Popen( | ||
[os.path.join(directory, 'setupc.exe'), 'install', 'PortName=%s' % m_name, 'PortName=%s' % s_name], | ||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=directory) | ||
stdout, stderr = p.communicate() | ||
logging.info('install stdout is %s' % stdout) | ||
logging.info('install stderr is %s' % stderr) | ||
|
||
if p.returncode != 0: | ||
raise Exception('com0com failure') | ||
logging.info('Sleeping a few second, it doesnt work in appveyour without it') | ||
time.sleep(10) | ||
return m_name, s_name | ||
|
||
|
||
def test_serial(m_name, s_name): | ||
master = Serial('\\\\.\\%s' % m_name, timeout=0) | ||
listen_thread = Listener(master, write, read) | ||
listen_thread.start() | ||
listen_thread.join() | ||
master.close() | ||
return stdout, stderr | ||
|
||
|
||
class Listener(threading.Thread): | ||
|
||
def __init__(self, port, write, read): | ||
# for windows write and read are methods from Serial object, for linux - os.read/write it doesnt work otherwise | ||
threading.Thread.__init__(self) | ||
self.port = port | ||
self.writer_process = None | ||
self.write = write | ||
self.read = read | ||
|
||
def run(self): | ||
start_time = time.time() | ||
while True: | ||
res = self.read(self.port, 9) | ||
if len(res) < 1: | ||
time.sleep(1) | ||
continue | ||
logging.info('read "%s"' % res) | ||
if 'F444' in res.decode('utf-8'): | ||
cur_time = time.time() | ||
resp = bytearray(struct.pack('d', (cur_time - start_time) * 1000)) | ||
self.write(self.port, resp) | ||
logging.info('sent resp to calc time command') | ||
elif 'b' in res.decode('utf-8'): | ||
self.writer_process = GaleaWriter(self.port, 0.005, self.write) | ||
self.writer_process.daemon = True | ||
self.writer_process.start() | ||
elif 's' in res.decode('utf-8'): | ||
if self.writer_process is not None: | ||
if self.writer_process.is_alive(): | ||
self.writer_process.need_data = False | ||
self.writer_process.join() | ||
else: | ||
# we dont handle commands to turn on/off channels, gain signal and so on. such commands dont change package format | ||
logging.info('got command "%s"' % res) | ||
|
||
|
||
class GaleaWriter(threading.Thread): | ||
|
||
def __init__(self, port, delay, write): | ||
threading.Thread.__init__(self) | ||
self.port = port | ||
self.write = write | ||
self.delay = delay | ||
self.package_size = 114 * 12 | ||
self.package_num = 0 | ||
self.need_data = True | ||
|
||
def run(self): | ||
while self.need_data: | ||
if self.package_num % 256 == 0: | ||
self.package_num = 0 | ||
|
||
package = list() | ||
package.append(0xA0) | ||
for i in range(self.package_size): | ||
package.append(random.randint(0, 255)) | ||
package.append(0xC0) | ||
logging.debug('package is %s' % ' '.join([str(x) for x in package])) | ||
self.write(self.port, bytes(package)) | ||
|
||
self.package_num = self.package_num + 1 | ||
time.sleep(self.delay) | ||
|
||
|
||
def main(): | ||
m_name, s_name = get_ports_windows() | ||
test_serial(m_name, s_name) | ||
|
||
|
||
if __name__ == '__main__': | ||
logging.basicConfig(level=logging.INFO) | ||
main() |
Oops, something went wrong.