I am getting an UnboundLocalError error when I run a python code that shouldn't result in an error according to most python users. The version of Packet Tracer is 8.0.0 and probably python 2
I was told that globing is not good to use instead I should use functions where I return the value.
Code:
from udp import *
from time import *
from gpio import *
def onUDPReceive(ip, port, data):
return int(data)
def main():
socket = UDPSocket()
temp=socket.onReceive(onUDPReceive)
print(socket.begin(1235))
while True:
if temp >= 520:#error
digitalWrite(3, HIGH);
delay(1000)
digitalWrite(3, LOW);
delay(500)
customWrite(9, 2);
else:
digitalWrite(0, LOW);
customWrite(2, 0);
if __name__ == "__main__":
main()
Error: UnboundLocalError: local variable 'temp' referenced before assignment in file main.py on line 15
What I have tried:
I have tired to print(temp);right after temp=socket.onReceive(onUDPReceive), but it still gives me the same error
When adding
try:
print(temp);
ParseError: bad input in file main.py on line 17
The system:
Image of code
Related
I am trying to configure python on my arduino. Ive followed like 10 tutorials but none of them are working. Ive tried to connect via pyserial. When I use pyserial, I simply get no response, here is the code.
I am trying to process data and code in python, then send data to arduino to run. I already downloaded the Firmata libraries on both, no issues there. I have also uploaded the arduino standard firmata sketch, no issues there.
Code being run on my python ide:
import serial
import time
Arduino = serial.Serial('com5',115200)
time.sleep(5)
while True:
while (Arduino.inWaiting()==0):
print("ur dumb")
pass
dataPacket = Arduino.readline()
print(dataPacket)
Code being run on my Arduino IDE:
int count = 1;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print(count);
delay(1000);
count = count+1;
}
Similary I've tried:
import pyfirmata
import time
board = pyfirmata.Arduino('/dev/ttyACM0')
it = pyfirmata.util.Iterator(board)
it.start()
digital_input = board.get_pin('d:10:i')
led = board.get_pin('d:13:o')
while True:
sw = digital_input.read()
if sw is True:
led.write(1)
else:
led.write(0)
time.sleep(0.1)
you can use a more accessible python program here to work:
import serial
import time
ArduinoUnoSerial = serial.Serial('com5',115200)
while 1:
print (ArduinoUnoSerial.readline())
this will work with your Arduino program
don't worry about the board no matter whether it is mega or uno or anything else ArduinoUnoSerial.readline() will work
Would anyone know when using python-shell if you can keep the python script running when its called from Javascript? Maybe call a method from a Python class from Javascript using python-shell?
For example this code works but it kills the Python script every time its called.
let {PythonShell} = require("python-shell");
let options = {
mode: "text",
args: ["read", "12345:2", "analogInput", "2"],
};
PythonShell.run("bac0Worker.py", options, function (err, results) {
if (err){
console.log(err)
console.log("An error happened")
}else{
// results is an array consisting of messages collected during execution
console.log("results: ", results);
console.log("Python Script Finished");
}
})
On the Python side I am experimenting with a package called BAC0 for BACnet systems. What I am trying to do is figure out if I can keep the BAC0 script running, I think under the hood of BAC0 there's alot of process going on where it may create lots of unnecessary traffic on a BACnet network if the script is started/stopped a lot.
bac0Worker.py
import sys
import BAC0
BAC0.log_level('silence')
bacnet = BAC0.lite()
def do_things(address,object_type,object_instance):
try:
read_vals = f'{address} {object_type} {object_instance} presentValue'
read_result = bacnet.read(read_vals)
if isinstance(read_result, str):
pass
else:
read_result = round(read_result,2)
print(read_result)
except Exception as error:
print("read error")
def main():
# args from Javascript
first = sys.argv[1]
second = sys.argv[2]
third = sys.argv[3]
fourth = sys.argv[4]
# get sensor data
do_things(second, third, fourth)
# all done
bacnet.disconnect()
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("bacnet app error")
bacnet.disconnect()
Like I mentioned the code works if I run from Node I can see the sensor value from the BACnet network 71.7 degrees.
C:\Program Files\nodejs\node.exe .\start.js
results: (1) ['71.7']
Python Script Finished
Hopefully this makes sense, sorry for the odd question but curious if anyone would have any tips for how to keep the Python script running where I could then just pass values (sensor & device addressing info) to BAC0 script to request a BACnet read from the network. In the main function of the Python file if I replace this:
# all done
bacnet.disconnect()
With:
while True:
pass
This would keep the Python file alive I just don't know how to pass values to a live Python script using python-shell. Thanks for any tips not a lot of wisdom here best practices. Curious if I should change my do_things function into a Python class with a method called do_things where then this class could get called from Javascript?
.js
const { PythonShell } = require("python-shell");
let pyshell = new PythonShell("my_script.py");
pyshell.send("hello");
pyshell.on("message", function (message) {
console.log(message);
});
setTimeout(() => {
pyshell.send("Another Hello");
}, 3000);
const end = () => {
pyshell.end(function (err, code, signal) {
if (err) throw err;
console.log("finished");
});
};
// end();
.py
import sys
def log():
print('hello from python')
while True:
inp = input(" ")
if inp=="hello":
log()
this will keep the process running unless you call the end method from the nodejs or some error occurs. This may incur performance issues because python thingy will be sharing same resources as your nodejs. A better way to do this would be to use a microservice like deploy some Rest Api which handles python specific tasks.
Just for fun Ill post what I was able to learn from #sandeep (thanks a million btw), this works. I can print BACnet sensor values which are gathered from Python from running a javascript file on 60 second setInterval(pythonDo, 60000); with keeping the Python file alive:
C:\Program Files\nodejs\node.exe .\start.js
BAC0 start success
68.47
68.43
68.29
68.25
start.js
const { PythonShell } = require("python-shell");
let pyshell = new PythonShell("bac0Worker.py");
function pythonDo() {
pyshell.send("read 12345:2 analogInput 2");
}
pyshell.on("message", function (message) {
console.log(message);
});
var data = setInterval(pythonDo, 60000);
bac0Worker.py
import sys
import BAC0
BAC0.log_level('silence')
bacnet = BAC0.lite()
print("BAC0 start success")
# available BACnet actions
SUBSTRING_READ = "read"
SUBSTRING_WRITE = "write"
SUBSTRING_RELEASE = "release"
def bac0_worker(action, BACnet_request, **kwargs):
value = kwargs.get('value', None)
priority = kwargs.get('priority', None)
if action == "read":
try:
read_vals = f'{BACnet_request} presentValue'
read_result = bacnet.read(read_vals)
if isinstance(read_result, str):
pass
else:
read_result = round(read_result,2)
print(read_result)
except Exception as error:
print("read error")
elif action == "write":
try:
write_vals = f'{BACnet_request} presentValue {value} - {priority}'
bacnet.write(write_vals)
print(write_vals)
except Exception as error:
print("write error")
elif action == "release":
try:
release_vals = f'{BACnet_request} presentValue null - {priority}'
bacnet.write(release_vals)
print(release_vals)
except Exception as error:
print("release error")
else:
return "server error on BACnet opts"
def main():
while True:
# from javascript
inp = input(" ")
for word in inp.split():
if SUBSTRING_READ == word:
stripped_string = inp.replace(SUBSTRING_READ + " ", "")
# do a BACnet READ request with BAC0
bac0_worker(SUBSTRING_READ,stripped_string)
if SUBSTRING_WRITE == word:
print("WRITE Match Found")
if SUBSTRING_RELEASE == word:
print("RELEASE Match Found")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("bacnet app error")
bacnet.disconnect()
Essentially, I've been trying to write a program that when you push a specific button, a specific image appears. For example, if I push Button1, Image1 will be displayed. Next, if I push Button2, Image1 will disappear and Image2 will displayed. The problem I ran into is regarding button2. Eventually, I would like it so that many image files can be opened. Right now, I have serial data being sent from the arduino to a raspberry pi with python. The python program recognizes button1 being pressed and displays the image. However, when I press button2 (before or after pressing button1), the program stops and an error message appears.
Any help to resolve this issue would be great!
I have tried altering the bytes sent from the Arduino but it was to no avail. I am new to serial data processing so there could be something I have missed.
Arduino Code
int First=2;
int buttonState=0;
int Second=3;
int buttonState2=0;
void setup()
{
Serial.begin(9600);
pinMode(First, INPUT);
pinMode(Second, INPUT);
}
void loop()
{
int buttonState=digitalRead(First);
int buttonState2=digitalRead(Second);
if(buttonState==HIGH)
{
Serial.print(0x0);
delay(100);
}
if (buttonState==LOW)
{
//do nothing
}
//BUTTON STATE SECOND
if(buttonState2==HIGH)
{
Serial.print(0x1);
delay(100);
}
if (buttonState2==LOW)
{
//do nothing
}
}
Python Code(The formatting for two lines is off due to how the question is posted):
import numpy
import cv2, glob
import sys
import os
import serial
from subprocess import Popen
ser=serial.Serial('/dev/ttyUSB0',9600)
Title = cv2.imread('/home/pi/Desktop/Avengers/Title.jpg')
Zero = cv2.imread('/home/pi/Desktop/Avengers/000.jpg')
while True:
command = ser.read()
if command:
#flush serial for unprocessed data
ser.flushInput()
print("new command:", command)
if (int(command) == 0):
cv2.namedWindow("Title", cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty("Title",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)
cv2.imshow('Title', Title)
cv2.waitKey(0)
cv2.destroyAllWindows()
if (int(command) == 1):
cv2.namedWindow("Zero", cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty("Zero",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)
cv2.imshow('Zero', Zero)
cv2.waitKey(0)
cv2.destroyAllWindows()
I expect one image to displayed when I push a button, and another image to be displayed when I push the other button. The results of the code allow one button to display an image. However, when the other button is pushed, no image is displayed. In short, one button works and the other doesn't. An error message reads:
Traceback (most recent call last):
File "/usr/lib/python3/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?)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/pi/OpenJPG.py", line 14, in <module>
command = ser.read()
File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 497, in read
raise SerialException('read failed: {}'.format(e))
serial.serialutil.SerialException: read failed: device reports readiness to read but returned no data (device disconnected or multiple access on port?)
How could I make an if/else condition about the status of myAarduino? If the status of my Arduino is connected, I want to have a Connected Message. If not, message is Disconnected.
import serial
serialTransferRate = 115200
arduinoPort = '/dev/tty.usbmodem411'
def connectToArduino():
arduino = serial.Serial(arduinoPort, serialTransferRate)
if(arduino.timeout == None):
print ("connected")
else:
print ("disconnected")
arduino = connectToArduino()
The error code below:
File "python", line 12, in <module>
File "python", line 6, in connectToArduino
SerialException: [Errno 2] could not open port /dev/tty.usbmodem411: [Errno
2] No such file or directory: '/dev/tty.usbmodem411'
The indentation should be like this, also you must use == for a comparison in an if statement and not = (which would be for assigning a value):
def connectToArduino():
try:
arduino = serial.Serial(arduinoPort, serialTransferRate)
except:
print 'disconnected'
else:
print 'connected'
arduino = connectToArduino()
The indentation in python is essential. Only things that would be placed in {} in other languages (e.g. C/C++) can and must be indented. If you indent just random code there will be the error message: unexpected indentation.
OK, so after searching a little too hard over the internet I still have my same issue. I have a very simple python script that opens up the specified excel file and then runs a macro.
I know for a fact that my python script runs as it should stand alone.
I know for a fact that my C++ code runs as it should.
But the combo of both creates a 'com_error'. Just so anyone who sees this knows, these are all the tests I have ran:
(1) simple python script (just prints hello) --> passed
(2) use C++ to run same simple .py script --> passed
(3) more advanecd python script (opens excel, runs macro, save and close) --> pass
(4) usc C++ code to run advanced .py script --> fail.
And there is my problem. this has something to do with the win32com.client and an error the server throws because it cant find the file location (but trust me it can because it passed the 'find file' test)
I'm running Windows7, Python 2.7, And the latest version of JetBrains Clion (2017.1.2).
Any help would be so appreciated. Thanks! Happy coding.
C++ code:
#include <iostream>
#include <Windows.h>
using namespace std;
int main() {
const char *cmd = "python C:\\Users\\Alex.Valente\\Desktop\\python.py";
PROCESS_INFORMATION processInformation = {0};
STARTUPINFO startupInfo = {0};
startupInfo.cb = sizeof(startupInfo);
BOOL result = CreateProcess(NULL, (LPSTR)cmd,
NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS,
GetEnvironmentStrings(), NULL, &startupInfo, &processInformation);
if(!result){
return -1;
}
WaitForSingleObject( processInformation.hProcess, INFINITE );
return 0;
}
Python Script:
from __future__ import print_function
import unittest
import os.path
import win32com.client
import os
class ExcelMacro(unittest.TestCase):
def test_excel_macro(self):
xlApp = win32com.client.DispatchEx('Excel.Application')
xlsPath = r'C:\Users\Alex.Valente\Desktop\Data.csv'
xlApp.Visible = True
wb = xlApp.Workbooks.Open(Filename=xlsPath)
xlApp.Run("PERSONAL.XLSB!PythonTest")
wb.Save()
wb.Close()
xlApp.Quit()
print("Macro ran successfully!")
if __name__ == "__main__":
unittest.main()
And the Error that is printed after I run it:
======================================================================
ERROR: test_excel_macro (__main__.ExcelMacro)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\Alex.Valente\Desktop\python.py", line 25, in test_excel_macro
wb = xlApp.Workbooks.Open(Filename=xlsPath)
File "<COMObject <unknown>>", line 8, in Open
com_error: (-2147417851, 'The server threw an exception.', None, None)
----------------------------------------------------------------------
Ran 1 test in 6.305s
FAILED (errors=1)