How to get a python server to convert recvline to a string? - python

How can I convert the input from the client from the server to a string or some other data type. My server can print the recvline from clients but doesn't recognize it as a common data type...
void timing()
{
for (long i = 0; i < 200000000; i ++){
printf("");
}
}
int main(int argc, char **argv){
int i;
int sockfd;
struct sockaddr_in servaddr;
char sendline[MAXLINE];
char recvline[MAXLINE];
time_t start, finish, final;
start = clock();
timing(); // a function that takes a differential time based on the client
finish = clock();
final = (finish - start) / CLOCKS_PER_SEC;
printf("timing: %ld\n", final);
if (argc != 2){
perror("usage: tcpcli <IPaddress>");
exit(-1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
char ** temp = NULL;
char * timing = NULL;
strtol(timing, temp, final); //***Problem here
write(sockfd, timing, 5);
bzero(recvline, MAXLINE);
if (read(sockfd, recvline, MAXLINE) == 0){ //reads from server
perror("Server terminated!");
exit(-1);
}
fputs(recvline, stdout);

Related

How to save an array from serial port to arduino (Save in EEPROM memory)

I trying to implement a project and I'm running in some issues. Well, I need to send an array from Python to arduino and save the array at EEPROM memory. I did some tests to save just ONE element at EEPROM memory and it worked preety well.
But, When I try to send the whole array, the data at EEPROM are ALL wrong. I think maybe it's because the time needed to write data in EEPROM memory.
Python
for i in range(0,156):
conexao.write(str(eeprom[i]).encode('utf-8'))
time.sleep(2)
conexao.close()
Arduino
#include <EEPROM.h>
String c;
int aux=0;
const int STARTING_EEPROM_ADDRESS = 0;
const int ARRAY_SIZE = 156;
int numbers[ARRAY_SIZE];
void writeIntArrayIntoEEPROM(int address, int numbers[],int element){
int x = element;
int addressIndex = address;
EEPROM.write(addressIndex, numbers[x] >> 8);
EEPROM.write(addressIndex + 1, numbers[x] & 0xFF);
while(Serial.read() >= 0); // I hope it clean the serial buffer
}
void readIntArrayFromEEPROM(int address, int numbers[], int arraySize)
{
int addressIndex = address;
for (int i = 0; i < arraySize; i++)
{
numbers[i] = (EEPROM.read(addressIndex) << 8) + EEPROM.read(addressIndex + 1);
addressIndex += 2;
}
}
void setup() {
Serial.begin(9600);
int newNumbers[ARRAY_SIZE];
readIntArrayFromEEPROM(STARTING_EEPROM_ADDRESS, newNumbers, ARRAY_SIZE);
for (int i = 0; i < ARRAY_SIZE; i++)
{
Serial.println(newNumbers[i]);
}
// Serial.println((EEPROM.read(0) << 8) + EEPROM.read(0 + 1));
}
void loop() {
while (Serial.available()>0){
for (int i=0; i < ARRAY_SIZE; i++) {
c=Serial.readStringUntil('\n');
numbers[i]=c.toInt();
writeIntArrayIntoEEPROM(aux, numbers[i], i);
aux +=2;
}
}
}

Trying to program ESP32 with manual switch feedback

i want to make a program where i can manage appliances using MQTT messages as well as i want to take feedback using normal switches, i tried the following code but in that case switch one and relay on is operating as expected but switch2 & switch 3 are getting called in loop and switch 2 is automatically getting converted from 0 to 1 and hence if condition is getting verified and its getting in loop, please help
#include <WiFi.h>
#include <PubSubClient.h>
#include "ArduinoJson.h"
#define relayOne 15
#define switchOne 32
#define relayTwo 2
#define switchTwo 35
#define relayThree 4
#define switchThree 34
#define relayFour 22
#define switchFour 39
const char* ssid = "*******";//replace this with your wifi access point
const char * password = ""*******";//"; //replace with your wifi password
const char * host = "*.*.*.*"; //IP address of machine on which broker is installed
const int port = 1883;
const char * mqttUser = "user";
const char * mqttPassword = "user";
WiFiClient espClient;
PubSubClient client(espClient);
StaticJsonBuffer < 55 > jsonBuffer;
void callback(char * topic, byte * payload, unsigned int length) {
Serial.print("Message received in topic: ");
Serial.print(topic);
Serial.print(" length is:");
Serial.println(length);
Serial.print("Data Received From Broker:");
String messageTemp;
for (int i = 0; i < length; i++) {
messageTemp += (char) payload[i];
}
//Serial.println(messageTemp);
const size_t capacity = JSON_OBJECT_SIZE(2) + 20;
DynamicJsonBuffer jsonBuffer(capacity);
//const char* json = "{\"pin\":14,\"value\":1}";
const char * json = messageTemp.c_str();
JsonObject & root = jsonBuffer.parseObject(json);
int pin = root["pin"];
int value = root["value"];
Serial.println(pin);
Serial.println(value);
digitalWrite(pin, value);
}
void setup() {
Serial.begin(115200);
pinMode(relayOne, OUTPUT);
pinMode(switchOne, INPUT_PULLUP);
pinMode(relayTwo, OUTPUT);
pinMode(switchTwo, INPUT_PULLUP);
pinMode(relayThree, OUTPUT);
pinMode(switchThree, INPUT_PULLUP);
pinMode(relayFour, OUTPUT);
pinMode(switchFour, INPUT_PULLUP);
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi..");
while (WiFi.status() != WL_CONNECTED) {
delay(100);
yield();
}
Serial.println("Connected to the WiFi network");
client.setServer(host, port);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP8266Client", mqttUser, mqttPassword)) {
Serial.println("connected to MQTT broker");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(500);
}
}
Serial.println("ESP32 AS SUBSCRIBER");
client.subscribe("IOT"); //topic name="Sub"
}
void MQTTPOST(int pin, int value)
{
Serial.println("in mqttpost");
//payload formation begins here
String payload ="{";
payload +="\"Pin\":"; payload +=pin; payload +=",";
payload +="\"Value\":"; payload +=value;
payload +="}";
char attributes[1000];
payload.toCharArray( attributes, 1000 );
client.publish("IOT1", attributes); //topic="Pub" MQTT data post command.
Serial.println( attributes );
Serial.println("");
}
int switchOneValue = 0;
int switchTwoValue = 0;
int switchThreeValue = 0;
int switchFourValue = 0;
void loop() {
client.loop();
int valueSwitchOne = digitalRead(switchOne);
Serial.println(valueSwitchOne);
Serial.println(switchOneValue);
if(valueSwitchOne == 0 && switchOneValue == 0){
digitalWrite(relayOne, 1);
switchOneValue = 1;
MQTTPOST(relayOne, 1);
Serial.println("on");
delay(200);
}else if(valueSwitchOne == 1 && switchOneValue == 1) {
digitalWrite(relayOne, 0);
switchOneValue = 0;
MQTTPOST(relayOne, 0);
Serial.println("off");
delay(200);
}
int valueSwitchTwo = digitalRead(switchTwo);
Serial.println(valueSwitchTwo);
Serial.println(switchTwoValue);
delay(1000);
if(valueSwitchTwo == 0 && switchTwoValue == 0){
digitalWrite(relayTwo, 1);
switchTwoValue = 1;
MQTTPOST(relayTwo, 1);
Serial.println("on2");
delay(200);
}else if(valueSwitchTwo == 1 && switchTwoValue == 1) {
digitalWrite(relayTwo, 0);
switchTwoValue = 0;
MQTTPOST(relayTwo, 0);
Serial.println("off2");
delay(200);
}
int valueSwitchThree = digitalRead(switchThree);
if(valueSwitchThree == 0 && switchThreeValue == 0){
digitalWrite(relayThree, 1);
switchThreeValue = 1;
MQTTPOST(relayThree, 1);
Serial.println("on");
delay(200);
}else if(valueSwitchThree == 1 && switchThreeValue == 1) {
digitalWrite(relayThree, 0);
switchThreeValue = 0;
MQTTPOST(relayThree, 0);
Serial.println("off");
delay(200);
}
}
here is a quote from documentation on esp32:
Appendix A – ESP32 Pin Lists
A.1. Notes on ESP32 Pin Lists
Table 24: Notes on ESP32 Pin Lists
GPIO pins 34-39 are input-only. These pins do NOT feature an output
driver or internal pull-up/pull-down circuitry.
digitalRead() can return arbitrary value for those pins because there are no built-in pull-up resistors there - they are effectively dangling in the air.
It means that following code CAN NOT WORK without external pull-up resistors:
#define switchTwo 35
#define switchThree 34
#define switchFour 39
pinMode(switchTwo, INPUT_PULLUP); // THIS DOES NOT WORK for GPIOs: 34-39!!!
pinMode(switchThree, INPUT_PULLUP); // THIS DOES NOT WORK for GPIOs: 34-39 !!!
pinMode(switchFour, INPUT_PULLUP); // THIS DOES NOT WORK for GPIOs: 34-39 !!!
// unpredictable values are here when button is not pressed
int valueSwitchTwo = digitalRead(35);
int valueSwitchThree = digitalRead(34);
Solution:
either use different pins for the switches
or add real hardware resistors into your schematics

Python ctypes cannot get long string value returned from .so file

I am learning C and trying to import a .so into my python file for higher performance by using a python package ctypes. So everything going well until I had a hard time when trying to get a string returned from .so file.
C code:
char *convert_to_16(char *characters, int n){
char sub_buffer[3];
char code[3];
char *buffer = (char*)malloc(sizeof(characters) * 2);
for(int i=0; i < n; i++){
strncpy(code, characters+i, 1);
sprintf(sub_buffer, "%x", *code);
strncat(buffer, sub_buffer, 2);
}
return buffer;
}
// main() only for test
int main(){
char param[] = "ABCDEFGHTUIKLL";
printf("%s\n", param);
int length = strlen(param);
printf("%s\n", convert_to_16(param, length));
}
It runs well with output:
41424344454647485455494b4c4c
Python code :
c_convert_to_16 = ctypes.CDLL('./convert_to_16.so').convert_to_16
c_convert_to_16.restype = ctypes.c_char_p
a_string = "ABCDEFGHTUIKLL"
new_16base_string = c_convert_to_16(a_string, len(a_string))
print new_16base_string
It runs but only returns two characters:
41
I read the official doc and set restype as ctypes.c_char_p, and try to set it to other values. But it seems it's the only option, just oddly only two characters were returned.
Is it the problem of my ctypes configuration or my C wasn't written correctly?
Many thanks.
I don't know much about ctypes in python but you should create your string like that c_char_p("ABCDEFGHTUIKLL").
And maybe tell what argument take your function c_convert_to_16.argtypes = [c_char_p, c_size_t]
This will fix your undefined behavior in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *convert_to_16(char const *array, size_t const len);
char *convert_to_16(char const *array, size_t const len) {
size_t const len_buffer = len * 2 + 1;
char *buffer = malloc(len_buffer);
if (buffer == NULL) {
return NULL;
}
size_t used = 0;
for (size_t i = 0; i < len; i++) {
if (len_buffer < used || len_buffer - used < 3) {
free(buffer);
return NULL;
}
int ret = snprintf(buffer + used, 3, "%.2x", (unsigned char)array[i]);
if (ret != 2) {
free(buffer);
return NULL;
}
used += 2;
}
return buffer;
}
int main(void) {
char const param[] = "ABCDEFGHTUIKLL";
printf("%s\n", param);
char *ret = convert_to_16(param, sizeof param - 1);
if (ret != NULL) {
printf("%s\n", ret);
}
free(ret);
}

The C extension Python I wrote crashes with "Abort trap: 6"

#include <stdio.h>
#include <Python/Python.h>
#include <string.h>
char *baseN(int num, char *LETTERS);
int myHash(char *s, char *LETTERS);
int indexOfString(char *s, char c);
char *lstrip(char *s, char strp);
void removeFirst(char *s);
static PyObject *ex_baseN(PyObject *self, PyObject *args) {
int num;
char *LETTERS;
if (!PyArg_ParseTuple(args, "is", &num, &LETTERS)) {
Py_RETURN_NONE;
}
char *result = baseN(num, LETTERS);
PyObject *retval = (PyObject *) Py_BuildValue("s", result);
return retval;
}
static PyObject *ex_myHash(PyObject *self, PyObject *args) {
char *s;
char *LETTERS;
if (!PyArg_ParseTuple(args, "ss", &s, &LETTERS)) {
Py_RETURN_NONE;
}
int result = myHash(s, LETTERS);
PyObject *retval = (PyObject *) Py_BuildValue("i", result);
return retval;
}
static PyMethodDef foo_methods[] = {
{"myHash", (PyCFunction) ex_myHash, METH_VARARGS},
{"baseN", (PyCFunction) ex_baseN, METH_VARARGS},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initmyEx() {
Py_InitModule3("myEx", foo_methods, "My first extension module.");
}
char *baseN(int num, char *LETTERS) {
int len = strlen(LETTERS);
if (num == 0) {
char *result = (char *) malloc(sizeof(char));
sprintf(result, "%c", LETTERS[0]);
return result;
}
char *s = baseN(num / len, LETTERS);
lstrip(s, LETTERS[0]);
char *result = (char *) malloc(sizeof(char) * (strlen(s) + 1));
int result_len = strlen(s) + 1;
for (int i = 0; i < result_len; i++) {
if (i < result_len - 1) {
result[i] = s[i];
} else {
result[i] = LETTERS[num % len];
}
}
return result;
}
void removeFirst(char *s) {
int len = strlen(s);
for (int i = 0; i < len; i++) {
if (i < len - 1) {
s[i] = s[i + 1];
} else {
s[i] = '\0';
}
}
}
char *lstrip(char *s, char strp) {
int len = strlen(s);
if (len >= 0) {
if (s[0] == strp) {
removeFirst(s);
}
}
return s;
}
int myHash(char *s, char *LETTERS) {
int h = 7;
int len = strlen(s);
for (int i = 0; i < len; i++) {
int index = indexOfString(LETTERS, s[i]);
h = 37 * h + index;
}
return h;
}
int indexOfString(char *s, char c) {
int len = strlen(s);
for (int i = 0; i < len; i++) {
if (s[i] == c) {
return i;
}
}
return -1;
}
int main(){
char * result = baseN(10119, "abcdefg");
printf("%s\n",result);
return 0;
}
I wrote a python extension of the above, but after compiling, and running in the Python interpreter ipython, the result is:
In [4]: myEx.myHash('asdfg','ascfwdzxfxcg')
Out[4]: 485465319
In [5]: myEx.baseN(1000,'asdfghj')
Abort trap: 6
The function named baseN does not work, why????
There is a buffer overflow in your code:
char *baseN(int num, char *LETTERS) {
int len = strlen(LETTERS);
if (num == 0) {
char *result = (char *) malloc(sizeof(char)); // 1 char allocated
sprintf(result, "%c", LETTERS[0]); // 2 chars written including NUL char
return result;
}
The current sprintf needs:
char *result = malloc(2);

Rate-limiting in python/arduino client/server communication

I'm trying to make a python client communicate with an arduino server. The python client asks the server to take a measurement from the sonar, and then server just sends a confirmation message and then takes the message.
The client:
client.py
import socket
import time
while True:
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("192.168.0.250", 10220))
data = "GET\nSONAR\n\n"
print 'send to server: ' + data
client_socket.send(data)
receive = client_socket.recv(2048)
print receive
client_socket.close()
time.sleep(0.1)
except Exception as msg:
print msg
and the server:
server.ino
#include <avr/wdt.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SoftwareSerial.h>
//localClient parameters, for sending data to the server.
byte mac[] = {0x90, 0xA2, 0xDA, 0x0F, 0x03, 0x58};
byte ip[] = {192,168,0,250};
byte server[] = {192, 168, 0, 100};
int serverPort = 8220;
//Server parameters, for acting like a server.
int pollPort = serverPort + 2000;
EthernetServer pollServer = EthernetServer(pollPort);
//char inString[32]; // string for incoming serial data
//sonar stuff
String content_string;
int NUM_SONARS = 1;
int sonarPin[] = {2, 3, 4, 5};
int triggerPin = 6;
int sonarThreshold = 12.0;
int sonarState[] = {0, 0, 0, 0};
long pulse;
int numPulses = 3;
int pulseArray[] = {0,0,0,0,0};
int filteredMode = 0;
float time;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac, ip);
wdt_enable(WDTO_8S);
pollServer.begin();
for(int i = 0; i < NUM_SONARS; i++) {
pinMode(sonarPin[i], INPUT);
}
pinMode(triggerPin, OUTPUT);
digitalWrite(triggerPin, LOW);
time = 0;
}
void loop() {
wdt_reset();
time = millis();
EthernetClient pollClient = pollServer.available();
if (pollClient) {
boolean currentLineIsBlank = true;
String receivingString = "";
while (pollClient.connected()) {
//while the socket is open
if(pollClient.available()) {
//and there is something to read on the port, then read the available characters
char c = pollClient.read();
receivingString += c;
if (c == '\n' && currentLineIsBlank) {
Serial.print("String received -- ");
Serial.print(receivingString);
Serial.print("at ");
Serial.println(time);
pollClient.println("Received message.");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// parse the incoming data
String command = split(receivingString,'\n',0);
String payload = split(receivingString,'\n',1);
String key = split(payload,'=',0);
String value = split(payload,'=',1);
//PARSE THE KEY AND VALUE NOW
if(command == "GET") {
//if I received a GET command, send a response to the client.
if(key == "SONAR") {
pingSonars();
}
}
}
String split(String data, char delimiter, int index) {
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==delimiter || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
void isort(int *a, int n) {
for (int i = 1; i < n; ++i) {
int j = a[i];
int k;
for (k = i - 1; (k >= 0) && (j < a[k]); k--) {
a[k + 1] = a[k];
}
a[k + 1] = j;
}
}
int mode(int *x,int n){
int i = 0;
int count = 0;
int maxCount = 0;
int mode = 0;
int bimodal;
int prevCount = 0;
while(i<(n-1)){
prevCount=count;
count=0;
while(x[i]==x[i+1]){
count++;
i++;
}
if(count>prevCount&count>maxCount){
mode=x[i];
maxCount=count;
bimodal=0;
}
if(count==0){
i++;
}
if(count==maxCount){//If the dataset has 2 or more modes.
bimodal=1;
}
if(mode==0||bimodal==1){//Return the median if there is no mode.
mode=x[(n/2)];
}
return mode;
}
}
void printArray(int *a, int n) {
for (int i = 0; i < n; i++)
{
Serial.print(a[i], DEC);
Serial.print(' ');
}
Serial.println();
}
void pingSonars() {
digitalWrite(6, HIGH);
for(int i = 0; i < NUM_SONARS; i++) {
for(int j = 0; j < numPulses; j++) {
pulse = pulseIn(sonarPin[i], HIGH);
pulseArray[j] = pulse/147; //convert to inches -- 147 uS per inches
delay(5);
}
isort(pulseArray, numPulses);
filteredMode = mode(pulseArray,numPulses);
//printArray(pulseArray,numPulses);
Serial.print("Filtered distance for Sonar ");
Serial.print(i);
Serial.print(": ");
Serial.println(filteredMode);
if((filteredMode < sonarThreshold) && !sonarState[i]) {
//if we are closer than the threshold and previously were not, this is a rising edge:
Serial.print("Sonar ");
Serial.print(i);
Serial.println(" triggered!");
sonarState[i] = 1;
}
else if (filteredMode > sonarThreshold && sonarState[i]) {
//if we are greater than the threshold and previously were, this is a falling edge:
Serial.print("Sonar ");
Serial.print(i);
Serial.println(" falling!");
sonarState[i] = 0;
}
}
}
The client sends requests at about a 100 millisecond interval, but the server seems to be able to respond much slower than that -- maybe at 2-3 times per second. What's limiting the rate of communication? Is it possible that the serial printouts are actually limiting it? Or does it have to do with how I'm opening/closing/listening to the port in the server code?
thanks for your help!

Categories