i used python on raspberry to read ph water from arduino - python

I create a project to read pH water, but my module sensor doesn't fix with raspberry pi 3 so I using Arduino to read pH, then send to raspberry and upload the data to firebase.
but, I have some problem, when raspberry read data from Arduino, the looping doesn't work. the error message is serial.util.serialexception
here's source code on Raspberry
import os
import serial
import time
from firebase import firebase
arduino = serial.Serial('/dev/ttyACM0',9600)
firebase = firebase.FirebaseApplication('https://raspi-ph.firebaseio.com/', None)
def update_firebase():
phair = arduino.readline()
if data is not None:
time.sleep(1)
pieces = data.split("sensor= ")
ph = pieces
print ph
else:
print('Failed to get data. Try Again!')
time.sleep(10)
data = {"Sensor pH": phair}
firebase.post('/sensor/ph', data)
while True:
update_firebase()
time.sleep(5)
and here's source code on Arduino
const int analogInPin = A0;
int sensorValue = 0;
unsigned long int avgValue;
float b;
int buf[10],temp;
void setup() {
Serial.begin(9600);
}
void loop() {
for(int i=0;i<10;i++)
{
buf[i]=analogRead(analogInPin);
delay(10);
}
for(int i=0;i<9;i++)
{
for(int j=i+1;j<10;j++)
{
if(buf[i]>buf[j])
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
avgValue=0;
for(int i=2;i<8;i++)
avgValue+=buf[i];
float pHVol=(float)avgValue*5.0/1024/6;
float phValue = -5.70 * pHVol + 21.34;
Serial.print("sensor = ");
Serial.println(phValue);
delay(20);
}
last, the error message on raspi
['seor= 0.52\r\n']
Traceback (most recent call last):
File "ard.py", line 27, in <module>
update_firebase()
File "ard.py", line 11, in update_firebase
phair = arduino.readline()
File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 490, in read
'device reports readiness to read but returned no data '
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)
the looping only run once

Looking at the source code, this exception is based on the assumption that ready for reading plus empty data implies a disconnected device.
The way to avoid this behaviour is to specify a timeout when creating a Serial instance.

Related

C++ serial communication write speed

I'm using uPyCraft IDE and Putty For communicating with serial "COM3" Port.
and I make a new C++ console Application for using serial port now.
but C++ console application's running speed is slower than Pychon.
How can I improve performance? is my code is something wrong?
this is what I tried in C++
int serialib::writeBytes(const void *Buffer, const unsigned int NbBytes)
{
DWORD dwBytesWritten;
if(!WriteFile(hSerial, Buffer, NbBytes, &dwBytesWritten, NULL))
return -1;
return 1;
}
void writedata(const char * arg)
{
string result = arg;
serial.writeBytes(&result,sizeof(result));
}
int main()
{
serial.openDevice("COM3", 115200);
if (serial.isDeviceOpen() != true)
{
return 1;
}
for (int i = 1;i <= 1000;i++)
{
writedata("km.move(0,1) ");
}
}
this is what I tried in Putty or uPyCraft
for i in range(1000) : km.move(0,1)
I couldn't find what point did I wrong
Speed is different more than double.
Putty and uPyCraft is Faster than C++ console
I don't know is writedata function causing delay
What is the best code for at C++ Console, writeBytes to commuinating with serial?
p.s : BaudRate, ByteSize, Stopbits, Pariety is same
BaudRate : 115200
ByteSize : 8
StopBits : 1
Pariety : NONE (0)

How can I set the file descriptors for a new Process in Haxe to use it with a socket?

I am translating some code to Haxe from Python so that I can target more platforms. But I'm having trouble with the following snippet.
import socket
from subprocess import Popen
host='127.0.0.1'
port=8080
file='handle.sh'
handler = socket.socket()
handler.bind((host, port))
handler.listen(5)
conn, address = handler.accept() # Wait for something to connect to the socket
proc = Popen(['bash', file], stdout=conn.makefile('wb'), stdin=conn.makefile('rb'))
proc.wait()
conn.shutdown(socket.SHUT_RDWR)
conn.close()
In Python, I can set stdin and stdout to the relevant file descriptors of the socket. But by the time I call shutdown, all the data to be sent is in the right buffer and nothing blocks me.
But I can't do this in Haxe as far as I can tell because input and output from the socket and, stdin and stdout from the process are all read-only.
I seem to get a deadlock with whatever I try. Currently I'm trying with a thread but it still gets stuck at reading from the socket.
#!/usr/bin/haxe --interp
import sys.net.Host;
import sys.net.Socket;
import sys.io.Process;
import sys.thread.Thread;
class HaxeServer {
static function main() {
var socket = new Socket();
var fname = 'handle.sh';
var host = '127.0.0.1';
var port = 8080;
socket.bind(new Host(host), port);
socket.listen(5);
while (true) {
var conn = socket.accept();
var proc = new Process('bash', [fname]);
exchange(conn, proc);
conn.output.write(proc.stdout.readAll());
proc.close();
conn.shutdown(true, true);
conn.close();
}
}
static function exchange(conn:Socket, proc:Process):Void {
#if (target.threaded)
Thread.create(() -> {
while (true) {
var drip = conn.input.readByte();
proc.stdin.writeByte(drip);
}
});
#end
}
}
Edit 1
Attempting to use the answer posted by #YellowAfterlife, I ran the following code instead of my exchange function.
conn.setBlocking(false);
Thread.create( () -> {
trace('--> read');
while (true) {
trace('-1a');
var data:Bytes = readAllNonBlocking(conn.input).bytes;
trace('-2a');
proc.stdin.write(data);
trace('-3a');
proc.stdin.flush();
}
});
trace('--> write');
while (true) {
trace('-1b');
var data:Bytes = readAllNonBlocking(proc.stdout).bytes;
trace('-2b');
conn.output.write(data);
trace('-3b');
conn.output.flush();
}
trace('Wait');
trace(proc.exitCode());
but it just logs this and hangs:
HaxeServer.hx:42: --> write
HaxeServer.hx:44: -1b
So it's not even getting into the thread and the input is still blocking.
If I put both read-write sections in threads, it just prints 'Wait'.
I have previously dealt (on a project bridging unrelated network APIs - GitHub repo) with the issue of reading all available data without deadlocking by marking the socket as non-blocking and implementing a custom function that reads all available data, like so:
public static function readAllNonBlocking(input:Input):{bytes:Bytes,eof:Bool} {
var total:BytesBuffer = new BytesBuffer();
var eof = false;
var len = 0;
try {
while (true) {
total.addByte(input.readByte());
len += 1;
}
} catch (x:Error) {
switch (x) {
case Blocked: // OK!
default: throw x;
}
} catch (x:Eof) {
eof = true;
}
var bytes:Bytes = total.getBytes();
if (bytes.length > len) {
bytes = bytes.sub(0, len);
}
return { bytes: bytes, eof: eof };
}
You will also likely need to .flush() stdin for data to actually make it to the process.

Send image from Android Studio to Python

I have some problems in my projects.
I send byte array from Android client to Python server and in Python server, I want to change byte array to Bitmap image file using PIL.Image.frombytes() but it occurs some error.
I can't handle this error. How I can handle it?
Bitmap from Android size is 640x480
public void request(){
handler = new Handler();
baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
final byte[] byteArray = baos.toByteArray();
Log.d("log1", Integer.toString(byteArray.length));
new Thread(new Runnable() {
#Override
public void run() {
Log.d("log1", "Start Thread to connect");
String newIP = "localhost";
int port = 5001;
try {
socket = new Socket(newIP, port);
Log.d("log1", "Correct Connect");
} catch (IOException e) {
Log.d("log1", "Not Connect");
e.printStackTrace();
}
try {
dos = new DataOutputStream(socket.getOutputStream());
dos.write(byteArray);
} catch (IOException e) {
e.printStackTrace();
Log.d("Buffer", "Incorrect Buffer");
}
This is my Android code to send bytearray to python server
In Log.d("log1", Integer.toString(byteArray.length));, result's length is same in python server received.
But To use PIL change byte array into Bitmap, there is error:
Traceback (most recent call last):
File "C:/Users/junso/PycharmProjects/Exercise/server2.py", line 39, in <module>
image = Image.frombytes('L', (width, height), bytes(data))
File "C:\Users\junso\PycharmProjects\Exercise\venv\lib\site-packages\PIL\Image.py", line 2615, in frombytes
im.frombytes(data, decoder_name, args)
File "C:\Users\junso\PycharmProjects\Exercise\venv\lib\site-packages\PIL\Image.py", line 800, in frombytes
raise ValueError("not enough image data")
ValueError: not enough image data

Uploading a file via POST multipart/form-data from windows phone 8.1 Silverlight Httpclient to python server corrupts files

Originally, I was using Windows Phone 8 System.Net.Http library to upload an image from SD card to a Python server with the following code:
private async void UploadFile()
{
try
{
// Make sure there is a picture selected
if (photoStream != null)
{
// initialize the client
// need to make sure the server accepts network IP-based
// requests.
// ensure correct IP and correct port address
var fileUploadUrl = #"http://IPAddress/";
var client = new HttpClient();
// Reset the photoStream position
// If you don't reset the position, the content lenght
// sent will be 0
photoStream.Position = 0;
// This is the postdata
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StreamContent(photoStream), "fn", fileName);
// upload the file sending the form info and ensure a result.
// it will throw an exception if the service doesn't return
// a valid successful status code
await client.PostAsync(fileUploadUrl, content)
.ContinueWith((postTask) =>
{
postTask.Result.EnsureSuccessStatusCode();
});
}
// Disable the Upload button
btnUpload.IsEnabled = false;
// reset the image control
DisplayImage.Source = null;
}
catch
{
}
}
In the server side, I used the following python code to decode the request:
ctype, pdict = cgi.parse_header(self.headers['content-type'])
data = cgi.parse_multipart(self.rfile, pdict)
It worked until I switched from Windows Phone 8 to Windows Phone 8.1 Silverlight. Since the System.Net.Http library is no longer supported in Windows Phone 8.1 Silverlight, I used Windows.Web.Http instead with modification of the code:
private async void UploadFile()
{
try
{
// Make sure there is a picture selected
if (file != null)
{
// initialize the client
// need to make sure the server accepts network IP-based
// requests.
// ensure correct IP and correct port address
var fileUploadUrl = new Uri(#"http://IPAddress/", UriKind.Absolute);
var client = new HttpClient();
HttpMultipartFormDataContent content = new HttpMultipartFormDataContent();
HttpStreamContent streamContent = new HttpStreamContent(photoStream);
content.Add(streamContent, "fn", fileName);
await client.PostAsync(fileUploadUrl, content);
}
// Disable the Upload button
btnUpload.IsEnabled = false;
// reset the image control
DisplayImage.Source = null;
}
catch
{
}
}
The server side is unchanged. However, the resulting file uploaded now has extra bytes inserted periodically that look something like '\r\n10000\r\n' or 0D 0A 31 30 30 30 30 0D 0A. The file also appears to begin and end with the same extra byte pattern. On the server pdict maps the boundary to something like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, but this seems to be the same behavior from when the file was uploaded via System.Net.Http.
I tried removing these bytes by hand on a smaller file which seemed to confirm that the file is otherwise correct.
Why are these extra bytes present? Is this a problem with the Python server mishandling the POST request?
Here's my solution when I encountered this issue:
Client:
public async Task UploadImage(byte[] image, string url)
{
Stream stream = new System.IO.MemoryStream(image);
HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
Uri resourceAddress = null;
Uri.TryCreate(url.Trim(), UriKind.Absolute, out resourceAddress);
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, resourceAddress);
request.Content = streamContent;
var httpClient = new Windows.Web.Http.HttpClient();
var cts = new CancellationTokenSource();
Windows.Web.Http.HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
}
Controller:
public async Task<HttpResponseMessage> Post()
{
Stream requestStream = await this.Request.Content.ReadAsStreamAsync();
byte[] byteArray = null;
using (MemoryStream ms = new MemoryStream())
{
await requestStream.CopyToAsync(ms);
byteArray = ms.ToArray();
}
.
.
.
return Request.CreateResponse(HttpStatusCode.OK);
}

Python PyBluez connecting to passkey protected device

I'm working on an application in Python (currently 2.7, can switch to 3.3 if necessary) that is supposed to:
Detect bluetooth device (finger clip pulse oximeter, if you're interested).
Establish connection with device (which is passkey protected)
Stream data from the device to my computer
Do more (currenly irrelevant) programming with the data
To accomplish this, I'm using the PyBluez library for Python, as it is probably the most documented library I've found (which sadly is still quite little) that is compatible with Windows and Python2.7.
I am very new to socket programming, so this is probably a simple question. The issue I've encountered, is that I cannot seem to figure out how to connect to the device since it is passkey protected. I can locate it and retrieve its address with no problem, I just don't know what port to use when connecting or how to enter a passkey.
Thanks for your help!
Reference Information:
Pulse oximeter used: http://www.echostore.com/wireless-oximeter-cms50e.html
PyBluez library: http://pybluez.googlecode.com/svn/www/docs-0.7/index.html
I meet the same problem,and I have resolved the problem, Maybe you can try it:
make a windows tool named pairtool.exe, it help you to pairing with command line.
dwRet = BluetoothAuthenticateDevice(NULL, NULL, &btdi, L"1234", 4);
if(dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
ExitProcess(2);
}
python code:
def connect2Btdev(devName):
#found the device addr
addr = inquiry(devName)
if addr == None:
return None
#pairing with pairtool.exe
cmd=r'%s %s' % ('pairtool.exe',addr)
ret = os.system(cmd)
if ret <> 0:
return None
PyBlueZ does not expose the windows Bluetooth authentication APIs here: https://msdn.microsoft.com/en-us/library/windows/desktop/cc766819(v=vs.85).aspx
One way to get around this is to create a command line tool and use this through Python. To create command line tools for Windows, use Visual Studio and add the necessary libraries to your project linker properties: Bthprops.lib and ws2_32.lib
Below is the code for a project to make a command line tool with 1 parameter, the MAC address, that pairs the specified device using "Just Works" pairing. See commented code for using passkey pairing.
#include "stdafx.h"
#include <initguid.h>
#include <winsock2.h>
#include <BluetoothAPIs.h>
#include <ws2bth.h>
BOOL WINAPI BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams);
int _tmain(int argc, _TCHAR* argv[])
{
SOCKADDR_BTH sa = { 0 };
int sa_len = sizeof(sa);
DWORD dwRet;
BLUETOOTH_DEVICE_INFO btdi = { 0 };
HBLUETOOTH_AUTHENTICATION_REGISTRATION hRegHandle = 0;
// initialize windows sockets
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
ExitProcess(2);
}
// parse the specified Bluetooth address
if (argc < 2) {
fprintf(stderr, "usage: csbtpair <addr>\n"
"\n addr must be in the form (XX:XX:XX:XX:XX:XX)");
ExitProcess(2);
}
if (SOCKET_ERROR == WSAStringToAddress(argv[1], AF_BTH,
NULL, (LPSOCKADDR)&sa, &sa_len)) {
ExitProcess(2);
}
// setup device info
btdi.dwSize = sizeof(BLUETOOTH_DEVICE_INFO);
btdi.Address.ullLong = sa.btAddr;
btdi.ulClassofDevice = 0;
btdi.fConnected = false;
btdi.fRemembered = false;
btdi.fAuthenticated = false;
// register authentication callback. this prevents UI from showing up.
dwRet = BluetoothRegisterForAuthenticationEx(&btdi, &hRegHandle, &BluetoothAuthCallback, NULL);
if (dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothRegisterForAuthenticationEx ret %d\n", dwRet);
ExitProcess(2);
}
// authenticate device (will call authentication callback)
AUTHENTICATION_REQUIREMENTS authreqs = MITMProtectionNotRequired;
fprintf(stderr, "BluetoothAuthReqs = %d\n", authreqs);
dwRet = BluetoothAuthenticateDeviceEx(NULL, NULL, &btdi, NULL, authreqs);
if (dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothAuthenticateDevice ret %d\n", dwRet);
if (dwRet == ERROR_CANCELLED)
{
fprintf(stderr, "Cancelled");
}
else if (dwRet == ERROR_INVALID_PARAMETER)
{
fprintf(stderr, "Invalid Parameter");
}
else if (dwRet == ERROR_NO_MORE_ITEMS)
{
fprintf(stderr, "Already paired!");
}
}
fprintf(stderr, "pairing finish\n");
ExitProcess(0);
return 0;
}
// Authentication callback
BOOL WINAPI BluetoothAuthCallback(LPVOID pvParam, PBLUETOOTH_AUTHENTICATION_CALLBACK_PARAMS pAuthCallbackParams)
{
DWORD dwRet;
fprintf(stderr, "BluetoothAuthCallback 0x%x\n", pAuthCallbackParams->deviceInfo.Address.ullLong);
BLUETOOTH_AUTHENTICATE_RESPONSE AuthRes;
AuthRes.authMethod = pAuthCallbackParams->authenticationMethod;
fprintf(stderr, "Authmethod %d\n", AuthRes.authMethod);
// Check to make sure we are using numeric comparison (Just Works)
if (AuthRes.authMethod == BLUETOOTH_AUTHENTICATION_METHOD_NUMERIC_COMPARISON)
{
fprintf(stderr, "Numeric Comparison supported\n");
}
AuthRes.bthAddressRemote = pAuthCallbackParams->deviceInfo.Address;
AuthRes.negativeResponse = FALSE;
// Commented out code is used for pairing using the BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY method
//memcpy_s(AuthRes.pinInfo.pin, sizeof(AuthRes.pinInfo.pin), L"1234", 0);
//AuthRes.pinInfo.pinLength = 0;
// Respond with numerical value for Just Works pairing
AuthRes.numericCompInfo.NumericValue = 1;
// Send authentication response to authenticate device
dwRet = BluetoothSendAuthenticationResponseEx(NULL, &AuthRes);
if (dwRet != ERROR_SUCCESS)
{
fprintf(stderr, "BluetoothSendAuthenticationResponseEx ret %d\n", dwRet);
if (dwRet == ERROR_CANCELLED)
{
fprintf(stderr, "Bluetooth device denied passkey response or communicatino problem.\n");
}
else if (dwRet == E_FAIL)
{
fprintf(stderr, "Device returned a failure code during authentication.\n");
}
else if (dwRet == 1244)
{
fprintf(stderr, "Not authenticated\n");
}
}
else
{
fprintf(stderr, "BluetoothAuthCallback finish\n");
}
return 1; // This value is ignored
}
In lieu of creating this yourself, you may want to try this pre-made solution:
http://bluetoothinstaller.com/bluetooth-command-line-tools/
It did not work for my particular solution.
Then, you will need to run your downloaded or custom command line tool from python as an administrator. To do this reliably, I recommend the stackoverflow question:
How to run python script with elevated privilege on windows

Categories