I have an accelerometer in my tablet, that I can read from within javascript.
How can I access this data in python? Is there some ctypes trickery I can use to call a windows 8 Sensor API function?
Horrible hack - start up a webserver in server.py:
import bottle
from threading import Thread
on_data = lambda alpha, beta, gamma: None
#bottle.route('/')
def handler():
return bottle.static_file('index.html', '.')
#bottle.post('/data')
def handler():
on_data(**bottle.request.json)
def data_handler(f):
global on_data
on_data = f
return f
def go():
t = Thread(target=lambda: bottle.run(quiet=True))
t.start()
With this index.html:
<script>
window.addEventListener('deviceorientation', function(eventData) {
var d = {};
['alpha', 'beta', 'gamma'].forEach(function(prop) {
d[prop] = eventData[prop];
})
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:8080/data");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send(JSON.stringify(d));
}, false);
</script>
And use it as:
import server
#server.data_hander
def on_acc_data(alpha, beta, gamma):
print alpha, beta, gamma
server.go()
After having opened localhost:8080/ in the browser
Related
My python program has several threads and they need to share (read and write) to the same object.
I am having problems, sometimes the value is stored correctly but other threads don't have it updated quick enough and only on a second or third interaction they have it updated.
this is my code:
from flask import Flask, render_template, request, jsonify
import threading
from time import sleep
from gpiozero import LED, Button, DigitalOutputDevice
SUM_ALARM_NC = LED(5)
SUM_ALARM_NO = LED(6)
SUM_ALARM_LED = LED(13)
SUM_ALARM_IN = Button(12)
from dataclasses import dataclass
import string
#dataclass
class Config_File:
status: string
serial_interface: string
changed:string
app = Flask(__name__, static_folder = 'assets')
#app.route("/")
def Index():
return render_template("index.html")
#app.route("/_monitoring")
def _monitoring():
return jsonify(_status = Config_File.status.strip(), _serial_interface = Config_File.serial_interface.strip())
#---------------------------------------------------------------------------------------------------------------
#app.route("/_saveserial")
def saveserial():
Config_File.changed = "1\n"
Config_File.serial_interface = str(request.args.get('RS232')) + "," + str(request.args.get('baudrate')) + "," + str(request.args.get('parity')) + "," + str(request.args.get('databit')) + "," + str(request.args.get('address')) + "\n"
return ""
def Monitoring_IO_thr():
while (True):
if SUM_ALARM_IN.is_pressed:
Config_File.changed = "0\n"
Config_File.status = "1\n"
SUM_ALARM_LED.on()
else:
Config_File.status = "0\n"
SUM_ALARM_LED.off()
sleep(0.5)
#### Save config_file class to the config.ini file ######################
def Save_Config_File_thr():
while (True):
if Config_File.changed == "1\n":
Config_File.changed = "0\n"
file_read = "config.ini"
fileobj = open(file_read,'r').readlines()
fileobj[3]= "Status:"+ Config_File.status
fileobj[21]= "Serial:" + Config_File.serial_interface
fileobj[55]= "Changed:" + Config_File.changed
# writes lines
with open(file_read,'w') as file:
file.writelines(fileobj)
file.close()
sleep(1)
if __name__ == "__main__":
Config_File.serial_interface="RS232,9600,Even,7,A\n"
Monitoring_IO_thread = threading.Thread(target = Monitoring_IO_thr)
Monitoring_IO_thread.start()
Save_Config_File_thread = threading.Thread(target = Save_Config_File_thr)
Save_Config_File_thread.start()
app.run(host='192.168.150.144', port=5050, debug=True)
Monitoring_IO_thread.join()
Save_Config_File_thread.join()
and this are my scripts
<script>
$(document).ready(function ()
{
$(function()
{
//SERIAL INTERFACE CHANGE - script to deal with the request to change the serial interface
$('#saveserial').on('click',function()
{
var data =
{
RS232: $('#RS232').val(),
baudrate: $('#baudrate').val(),
parity: $('#parity').val(),
databit: $('#databit').val(),
address: $('#address').val(),
};
$.getJSON("/_saveserial", data, function ()
{
});
});
});
$(function monitoring()
{
$.getJSON('/_monitoring', function(data)
{
if (data._status == "1")
{
$("#alarm_on").attr("hidden", false);
$("#alarm_off").attr("hidden", true);
}
if (data._status == "0")
{
$("#alarm_on").attr("hidden", true);
$("#alarm_off").attr("hidden", false);
}
setTimeout(function(){monitoring();},500);
});
}
);
});
</script>
How can I share Config_File between threads?
After your precious help I tried the following:
from multiprocessing import Process, Lock
mutex=Lock()
def Monitoring_IO_thr():
mutex.acquire()
try:
while(True):
Inputs_Monitoring()
sleep(0.5)
finally:
mutex.release()
def Save_Config_File_thr():
mutex.acquire()
try:
while(True):
if Config_File.changed == "1\n":
Config_File.serial_interface)
#save to file
Config_File.changed = "0\n"
Save_config()
out("saving config.ini")
sleep(1)
finally:
mutex.release()
if __name__ == "__main__":
Init()
app.run(host='192.168.150.144', port=5050, debug=True)
while(True):
Monitoring_IO_thread = threading.Thread(target = Monitoring_IO_thr)
Monitoring_IO_thread.start()
Save_Config_File_thread = threading.Thread(target = Save_Config_File_thr)
Save_Config_File_thread.start()
Not sure why but the program never runs both threads... any ideas what am I doing wrong?
I'm working on a project, where I have to connect Python and C# in a rather flexible way, with information being send from one to the other frequently. Most of the time, the data goes back and forth (A works with data, sends result to B, B works with result, answers A) but not necessary always.
Named pipes seemed like the way to go but I'm struggling with keeping it all synchronous.
Currently I'm just starting a server on one of them and let it wait for a client connection, while the other creates a server as well, and connects as a client when the server is ready.
It's a lot of creating servers and clients and trying to not break it, which happens as soon as a client tries to connect to an not existing server..
I'd like to do it with a pipe that runs in a separate thread, but couldn't find a way to keep it alive, it simply closes, when the client is done reading.
Are named pipes just too simplistic for such a task, or is there a way to make this work robustly?
Update:
For reference, how my code looks like (reduced to the minimum here):
First the NamedPipe Server and Client in C#
public static void SendDataToPython(string payload)
{
using (var server = new NamedPipeServerStream("Test"))
{
server.WaitForConnection();
using (var stream = new MemoryStream())
using (var writer = new BinaryWriter(stream))
{
writer.Write(payload);
server.Write(stream.ToArray(), 0, stream.ToArray().Length);
}
server.Disconnect();
}
}
public static string WaitForMessage()
{
string message = "";
string servername = ".";
string pipeName = "CSServer";
using (var pipeClient = new NamedPipeClientStream(servername, pipeName, PipeDirection.In))
{
pipeClient.Connect();
And in Python:
class PipeServer():
def __init__(self, pipeName):
self.pipe = win32pipe.CreateNamedPipe(
r'\\.\pipe\\' + pipeName,
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
1, 65536, 65536,
0,
None)
def connect(self):
win32pipe.ConnectNamedPipe(self.pipe, None)
def write(self, message):
win32file.WriteFile(self.pipe, message.encode() + b'\n')
def close(self):
win32file.CloseHandle(self.pipe)
using (StreamReader sr = new StreamReader(pipeClient))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
message += temp;
}
}
}
return message;
}
class PipeClient:
def __init__(self, pipeName):
self.pipeName = pipeName
def receive(self):
file_handle = win32file.CreateFile(
f"\\\\.\\pipe\\{self.pipeName}",
win32file.GENERIC_READ | win32file.GENERIC_WRITE,
0,
None,
win32file.OPEN_EXISTING,
0,
None)
left, data = win32file.ReadFile(file_handle, 4096)
print(data.decode("utf-8")[1:])
I saw that this problem is quite common, but I couldn't figure it out how to solve it in my case.
I'm creating a server in Python like this:
clients = []
server = None
class SimpleWSServer(WebSocket):
def handleConnected(self):
clients.append(self)
def handleClose(self):
clients.remove(self)
def run_server():
global server
server = SimpleWebSocketServer('', 9000, SimpleWSServer,
selectInterval=(1000.0 / 15) / 1000)
server.serveforever()
t=threading.Thread(target=run_server)
t.start()
if( ...)
for client in clients:
msg = json.dumps({'x': cX, 'y': cY})
client.sendMessage(unicode(msg))
and I'm open a WebSocket using three.js in this way:
var ws = new WebSocket('ws://192.168.0.15:9000/');
ws.onopen = function() {
console.log('onopen');
};
ws.onmessage = function (event) {
var m = JSON.parse(event.data);
history.push({ x: m.x * 2 - 1, y: -m.y * 2 + 1});
window.alert("X: "+x + " Y "+ y)
// ... rest of the function.
};
The localhost server is created using node.js and I don't have any errors in the log, meanwhile in Google Chrome I have the error: " threejs_prova.js:3 WebSocket connection to 'ws://192.168.0.15:9000/' failed: Connection closed before receiving a handshake response"
Error in Firefox is:
Firefox can't connect to server ws://192.168.0.15:9000/
In my case changing
var ws = new WebSocket('ws://192.168.0.15:9000/');
with
var ws = new WebSocket('ws://localhost:9000/');
solved the problem
I've been trying to implement the python equivalent of the code below but cannot seem to get it working.
var io = require('socket.io-client')
var socket = io('http://devel.hz.udoidio.info:5000')
socket.on('connect', function () {
socket.emit('subscribe', 'new-tx')
})
socket.on('new-tx', function (txid) {
console.log('New tx: ' + txid)
})
I tried this approach but it does not seem to yield anything.
from socketIO_client import SocketIO, LoggingNamespace
def on_response(*args):
print 'on_response', args
baseurl = "http://v1.livenet.bitcoin.chromanode.net"
socketIO = SocketIO(baseurl, 80, LoggingNamespace)
socketIO.on('subscribe', on_response)
socketIO.emit('subscribe', 'new-block')
socketIO.wait()
I resloved the problem, below is the correct solution.
from socketIO_client import SocketIO
def on_response(*args):
print 'on_response', args
baseurl = "http://devel.hz.udoidio.info"
with SocketIO(baseurl, 5000) as socketIO:
socketIO.on('new-tx', on_response)
socketIO.emit('subscribe', 'new-tx')
socketIO.wait()
I need to receive data from device connected via Ethernet (modbus/TCP) and send it to webpage (maybe using web sockets).
I can't find good examples. Now I can connect with driver and print values using ModbusClientProtocol.read_input_registers() but I had to create own factory and protocol class. I am using autobahn, twisted, pymodbus.
I've no familiarity with modbus or pymodbus, so I'm guessing and leaving a lot of blanks for you to fill in.
This is hacked out of something I recently put together to receive snmptraps and redistribute the information to connected websockets.
Hopefully this is enough to get you going:
#!/usr/bin/python
from twisted.internet import protocol, reactor, utils, defer
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.websocket import WebSocketServerFactory, WebSocketServerProtocol
from autobahn.util import newid
from autobahn.resource import WebSocketResource
class ModbusThing(object):
def __init__(self,clientAddress):
self.clientAddress = clientAddress
self.client = None
def start(self):
pass
## Create client connection to modbus server
## Start Looping Call of pollForData with suitable interval
def pollForData(self):
pass
## Call read methods on ModbusClient object, add call backs to process the results
## Add errorBacks to notify of errors
def resultCallback(self,result):
pass
## Process the data from a read request
## Assumes that your websocket clients expect json like {"event":"update","data":[0,1,2]}
message = dict(event="update",data=processedResults)
self.broadcast(json.dumps(message))
def broadcast(self,msg):
"""Override me"""
pass
class TrackingWebSocketProtocol(WebSocketServerProtocol):
def onOpen(self):
self.session_id = newid()
self.factory._addSession(self,self.session_id)
print "Socket Open %s" % (self.peerstr,)
def onMessage(self,payload,isBinary):
print "Message received from %s\n\t: %r" % (self.peerstr,payload)
def onClose(self,wasClean,code,reason):
self.factory._removeSession(self)
print "Socket Closed %s" % (self.peerstr,)
class TrackingWebSocketFactory(WebSocketServerFactory):
def __init__(self,*args,**kwargs):
WebSocketServerFactory.__init__(self,*args,**kwargs)
self.proto2session = {}
self.session2proto = {}
def _addSession(self,proto,session_id):
if not self.proto2session.has_key(proto):
self.proto2session[proto] = session_id
else:
raise Exception("logic error - dublicate _addSession for protoToSessions")
if not self.session2proto.has_key(session_id):
self.session2proto[session_id] = proto
else:
raise Exception("logic error - dublicate _addSession for sessionsToProto")
def _removeSession(self,proto):
if proto in self.proto2session:
session_id = self.proto2session[proto]
del self.proto2session[proto]
if session_id in self.session2proto:
del self.session2proto[session_id]
def sendToAll(self,message,binary=False):
prepped = self.prepareMessage(message,binary)
for proto in self.proto2session.keys():
proto.sendPreparedMessage(prepped)
def run():
## WebSocket Factory
wsfactory = TrackingWebSocketFactory('ws://yourhostname:80')
wsfactory.protocol = TrackingWebSocketProtocol
wsresource = WebSocketResource(wsfactory)
## Modbus handler
modbus_thing = ModbusThing((addressofserver,portofserver))
modbus_thing.broadcast = wsfactory.sendToAll
modbus_thing.start()
## WebServer Site
# "static" subdirectory, containing http served resources, e.g. index.html, javascript and css
root = File("static")
# Your websocket service as 'ws://yourhostname/ws'
root.putChild("ws", wsresource)
site = Site(root)
reactor.listenTCP(80,site)
def main():
reactor.callWhenRunning(run)
reactor.run()
if __name__=='__main__':
main()
On the browser side of things. A little module for interacting with websockets is handy:
var FancyWebSocket = function(url){
var conn = null;
var fws = this;
if ("WebSocket" in window) {
conn = new WebSocket(url);
} else if ("MozWebSocket" in window) {
conn = new MozWebSocket(url);
} else {
console.log("Error Websockets not supported in browser");
return;
}
var callbacks = {};
var debug = true;
this.bind = function(event_name, callback){
callbacks[event_name] = callbacks[event_name] || [];
callbacks[event_name].push(callback);
return this;// chainable
};
this.send = function(event_name, event_data){
var payload = JSON.stringify({event:event_name, data: event_data});
conn.send( payload ); // <= send JSON data to socket server
return this;
};
this.close = function(){ conn.close(); return this;}
// dispatch to the right handlers
conn.onmessage = function(evt){
if (debug) console.log("Websocket(" + conn.URL + ") Message: " + evt.data)
var json = JSON.parse(evt.data)
dispatch(json.event, json.data)
};
conn.onclose = function(){
if (debug) console.log("Websocket(" + conn.URL + ") Closed");
dispatch('close',fws);
}
conn.onopen = function(){
if (debug) console.log("Websocket(" + conn.URL + ") Open");
dispatch('open',fws);
}
conn.onerror = function(e){
if (debug) console.log("Websocket(" + conn.URL + ") Error: " + error);
dispatch('error',fws,e);
}
this.setdebug = function(v) { debug=v; return this; }
var dispatch = function(event_name, message){
var chain = callbacks[event_name];
if(typeof chain == 'undefined') return; // no callbacks for this event
for(var i = 0; i < chain.length; i++){
chain[i]( message )
}
}
};
Then in your browser console:
conn = new FancyWebSocket("ws://yourhostname/ws");