Control 2 relays with micropython - iot

Can some one help me with a problem.
I have an ESP32 board with GPIO pin 25 and 27 connected to a 2 relay board and with a webserver.
At boot one relay is low and one is high then the code behind the webpage is
while True:
try:
if gc.mem_free() < 102000:
gc.collect()
conn, addr = s.accept()
conn.settimeout(3.0)
print('Got a connection from %s' % str(addr))
request = conn.recv(1024)
conn.settimeout(None)
request = str(request)
print('Content = %s' % request)
relay_on = request.find('/?relay=on')
relay_off = request.find('/?relay=off')
if relay_on == 6:
print('RELAY ON')
relay_a.value(0)
relay_b.value(1)
if relay_off == 6:
print('RELAY OFF')
relay_a.value(1)
relay_b.value(0)
response = web_page()
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(response)
conn.close()
except OSError as e:
conn.close()
print('Connection closed')
but with this cod only relay_a is getting triggered on an off.
Thanks in advance!

Related

How to siimulate thousands of devices in Node-red

I have created a simulation of a device using Node red . Basically the device send UDP packets every second until it receives an acknowledgement. I have done that successfully
The problem is am trying to simulate 10000 of such devices. Hence I would need to automate the device creation/enrollment process. Is there a way I can achieve this in Node-red
The json below shows how one device is supposed to behave. it sends a UDP packet to a server and waits for an ACK . If the ACK is not received within a time period, It resends the packet.
Here is the node-red JSON of one device.
[{"id":"a53cc152.31f27","type":"comment","z":"d51aa60c.64d028","name":"Listener","info":"","x":106,"y":134,"wires":[]},{"id":"a972f44d.eaa9e8","type":"comment","z":"d51aa60c.64d028","name":"Sender","info":"","x":136,"y":332,"wires":[]},{"id":"ff1376ae.e08a58","type":"function","z":"d51aa60c.64d028","name":"stringToBytes ","func":"//var binary = msg.payload.toString(2);\n// 6 because it's zero based count\n//var bit7 = binary.charAt(6);\n//msg.payload = bit7;\n//return msg;\n str=msg.payload\n var ch, st, re = [];\n for (var i = 0; i < str.length; i++ ) {\n ch = str.charCodeAt(i); // get char \n st = []; // set up \"stack\"\n do {\n st.push( ch & 0xFF ); // push byte to stack\n ch = ch >> 8; // shift value down by 1 byte\n } \n while ( ch );\n // add stack contents to result\n // done because chars have \"wrong\" endianness\n re = re.concat( st.reverse() );\n }\n msg.payload=re\n // return an array of bytes\n return msg;\n\n","outputs":1,"noerr":0,"x":566,"y":381,"wires":[["98c6c5a8.aaf1c8"]]},{"id":"85d26758.5ee0f8","type":"function","z":"d51aa60c.64d028","name":"ConfigMessge","func":"msg.payload='830546613660520101010201225A8622475A862247E96665D15684EF030000242D0000000000E308000001FFA94F0A1F00FF0B08000000000000002E50000000000000000000000000000000000000000000000000'\nmsg.ip = '127.0.0.1'\nmsg.port='57920'\nreturn msg;","outputs":1,"noerr":0,"x":353,"y":375,"wires":[["ff1376ae.e08a58"]]},{"id":"c83f781f.ae3428","type":"debug","z":"d51aa60c.64d028","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":919,"y":632,"wires":[]},{"id":"98c6c5a8.aaf1c8","type":"http request","z":"d51aa60c.64d028","name":"ParserAPIRequest","method":"GET","ret":"txt","url":"http:/api","tls":"","x":590,"y":529,"wires":[["eac23a48.b479d8","66759bdf.7fd864"]]},{"id":"4a724471.e5158c","type":"inject","z":"d51aa60c.64d028","name":"TimerTrigger","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":148,"y":377,"wires":[[]]},{"id":"eac23a48.b479d8","type":"http response","z":"d51aa60c.64d028","name":"ParserAPIResponse","statusCode":"200","headers":{"content-type":"application/json"},"x":602,"y":614,"wires":[]},{"id":"66759bdf.7fd864","type":"function","z":"d51aa60c.64d028","name":"CheckForAck?","func":"// Loop function\n\ncontext.loops = context.loops || 0;\nmsg\nif (context.loops!==0)\n{\n\n\ncontext.ACK =0\ncontext.ACK=flow.get('ACK')|| 0;\n//msg.payload=context.ACK\nif(context.ACK === 1 ) \n { \n //\n//return msg;\n return [null, null];\n }\nelse\n{\n // msg.payload='No ACK triggered'+ context.ACK\n context.loops = context.loops + 1\n \n}\n \n \n}\n return [msg, msg];\n","outputs":"2","noerr":0,"x":857,"y":364,"wires":[["faa8c055.7dd7d","f8eb8444.61e8f8","a3286965.3120d8"],[]]},{"id":"a3286965.3120d8","type":"udp out","z":"d51aa60c.64d028","name":"Resend Packet","addr":"127.0.0.1","iface":"","port":"","ipv":"udp4","outport":"13500","base64":false,"multicast":"false","x":1116,"y":230,"wires":[]},{"id":"faa8c055.7dd7d","type":"debug","z":"d51aa60c.64d028","name":"Console.log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":1095,"y":494,"wires":[]},{"id":"f8eb8444.61e8f8","type":"delay","z":"d51aa60c.64d028","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":848,"y":420,"wires":[["66759bdf.7fd864"]]},{"id":"637d9a4c.1182d4","type":"udp in","z":"d51aa60c.64d028","name":"RecieveAck","iface":"","port":"13501","ipv":"udp4","multicast":"false","group":"","datatype":"utf8","x":173,"y":177,"wires":[["8b85adf3.38d6d"]]},{"id":"8b85adf3.38d6d","type":"switch","z":"d51aa60c.64d028","name":"AssignAck","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"'ACK'","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":384,"y":193,"wires":[["1d63307c.82e67"]]},{"id":"66ffd66c.b3c118","type":"function","z":"d51aa60c.64d028","name":"StoreAckInContext","func":"context.ACK=0\nflow.set('ACK',1);\nmsg.payload=flow.get('ACK')\n\nreturn msg;","outputs":1,"noerr":0,"x":717,"y":178,"wires":[["be667fba.f6701"]]},{"id":"be667fba.f6701","type":"debug","z":"d51aa60c.64d028","name":"Console.log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":909,"y":155,"wires":[]},{"id":"1d63307c.82e67","type":"change","z":"d51aa60c.64d028","name":"Reset","rules":[{"t":"set","p":"ACK","pt":"flow","to":"0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":165,"wires":[["66ffd66c.b3c118"]]},{"id":"68ded0.44db513","type":"status","z":"d51aa60c.64d028","name":"","scope":["66759bdf.7fd864"],"x":667,"y":282,"wires":[["a3286965.3120d8"]]}]

SATA driver; AHCI port initialisation; Start (ST) command list;

I have an issue with initialising and running AHCI port on my devboard.
Processor has SATA host controller with 2 ports implemented (port 0 & port 1). SSD drive w/ SATA interface is connected to the port 1.
According to "Serial ATA AHCI 1.3.1 Specification", chapter "10.3.1 Start (PxCMD.ST)" a bunch of conditions should be satisfied before setting PxCMD.ST to '1'. After setting this bit, PxCMD.CR should be set to indicate that port is ready and runs.
The problem is PxCMD.CR never comes to be set.
State before enabling PxCMD.ST:
port is in idle state, PxCMD.ST and PxCMD.CR are both '0'
FIS Receive Enable, PxCMD.FRE is '1'
Drive is connected to the port, PxSSTS = 0x00000133 (SSTS.IPM =
1, SSTS.SPD = 3, SSTS.DET = 3), PxTFD = 0x00000150 (TFD.STS.BSY
= 0, TFD.STS.DRQ = 0, TFD.STS.ERR = 0)
PxCLB/PxCLBU are set with physical addresses to buffer and buffer is aligned. (1KB buffer, 1KB aligned)
PxCMD = 0x00404010 (PxCMD.FBSCP = 1 & PxCMD.FRE = 1)
After setting PxCMD.ST, PxCMD = 0x00404011 and PxCMD.CR stays '0'
PxSERR = 0 stay the same. ERR is cleaned in advance before setting PxCMD.FRE
PxSCTL = 0x00000330 (IPM = 3, SPD = 3, DET = 0)
PxTFD = 0x00000150 stay the same
PxSIG = 0x00000101. The reg has 0xFFFFFFFF when drive is not connected.
Assuming that PxSIG is set and PxSERR is '0' more likely that PLL for SATA HC is set correctly.
I have concerns about PxTFD.ERR = 1 (when drive is disconnected PxTFD has default 0x7F value and PxTFD.ERR = 0) but didn't find is it relevant or nor considering that still TFD.STS.ERR = 0
Any ideal what is missed?
PS: It has nothing to do w/ Linux.

Lua: publish different sensors data simultaneously to topic

I am able to publish a data of different sensors (like temperature value and motion detection as zero or one) one at a time on a specific topic ( topic/temp/motion) using Lua code and subscribe in on my android app however i am not able to publish it simultaneously on same topic or sub-topic. Some ideas or examples would be great.
Below are some major bits of Lua code used.
orgID = "quickstart" -- IoT Foundation organization ID
broker = "test.mosquitto.org" --orgID..".messaging.internetofthings.ibmcloud.com" -- IP or hostname of IoTF service
mqttPort = 1883 -- MQTT port (default 1883: non-secure)
userID = "" -- blank for quickstart
userPWD = "" -- blank for quickstart
macID = "18fe34e1b007" -- unique Device ID or Ethernet Mac Address <==== Modify this!
clientID = ":esp8266:18fe34e1b007" -- Client ID
count = 0 -- Test number of mqtt_do cycles
mqttState = 0 -- State control
topic = "topic/temp/motion"
led = 4
--gpio.mode(led,gpio.OUTPUT)
--dht sensor settings------------------------------
pin = 1
-- PIR initialization section
pir = 2
x= 0 -- variable for sending motion detection information in "0 or 1"
function DHT_do()
status, temp, humi, temp_dec, humi_dec = dht.read(pin)
--gpio.write(led, gpio.LOW)
end
function mqtt_do()
count = count + 1 -- tmr.alarm counter
------------------------------------------- pir conditional code
if gpio.read(pir) ~= last_state then
last_state = gpio.read(pir)
if last_state == 1 then
print("ON")
x = 1
gpio.write(led,gpio.HIGH)
else
print("OFF")
x = 0
gpio.write(led,gpio.LOW)
m:publish(topic,x, 0, 0,
function(conn)
print(x)
print("temp_data:"..temp)

How can I maximize throughput in Docker and Akka HTTP?

I am building a specific jig for performance measurement. I have a load generator, boom (https://github.com/rakyll/boom). With this I can generate a pretty decent amount of load.
I also have a Docker image containing nginx as a load balancer, and two Akka-HTTP based REST servers. These do nothing except count hits (they always just return 200).
Running one of these servers stand-alone (outside the Docker) I have been able to get 1000 hits/second. Not sure if that's good or not. In this Docker configuration that figure drops to about 220 hits/second. I was kinda expecting, well... 2000 hits/second or thereabouts. Higher would even be better. I'd be happy if I can find a way to get 3-4K hits/sec with this arrangement.
I often get an error message like this:
[9549] Get http://192.168.99.100:9090/dispatcher?reply_to=foo: dial tcp 192.168.99.100:9090: socket: too many open files
Tried running my Docker with --ulimit nofile=2048, but that didn't help. My application.conf for Akka is merely:
akka {
loglevel = "ERROR"
stdout-loglevel = "ERROR"
http.host-connection-pool.max-open-requests = 512
}
The server code:
object Main extends App {
implicit val system = ActorSystem()
implicit val mat = ActorMaterializer()
println(":: Starting Simulator on port "+args(0))
Http().bindAndHandle(route, java.net.InetAddress.getLoopbackAddress.getHostAddress, args(0).toInt)
var hits = 0
var isTiming = false
var numSec = 1
lazy val route =
get {
path("dispatcher") {
if(isTiming) hits += 1
complete(StatusCodes.OK)
} ~
path("startTiming" / IntNumber) { sec =>
isTiming = true
hits = 0
numSec = sec
val timeUnit = FiniteDuration(sec, SECONDS)
system.scheduler.scheduleOnce(timeUnit){ isTiming = false }
complete(StatusCodes.OK)
} ~
path("tps") {
val tps = hits/numSec * 2
complete(s"""${args(0)}: TPS-$tps\n""")
}
}
}
Theory of operation: Start traffic flowing then call the /startTiming/10 endpoint (for a 10-second capture on one of the 2 servers). After 10 seconds, call /tps a couple of times and the timing node will return approx. hits/second (x2).
Any idea how I can get more performance out of this?

Wireshark does not get Scapy Modbus response

I'm running the code example below against a remote PLC with Wireshark running. Why do I only get the query (I should get the response too)? It seems that the PLC sends the response, since the output of Scapy says Received 1 packets, got 1 answers, remaining 0 packets.
Any ideas of why is this happening?
I also performed the sniffing using the sniff() function from Scapy but the result is the same (only get the query).
#! /usr/bin/env python
import logging
logging.getLogger("scapy").setLevel(1)
from scapy import *
from modLib import *
# IP for all transmissions
ip = IP(dst="192.168.10.131")
# Sets up the session with a TCP three-way handshake
# Send the syn, receive the syn/ack
tcp = TCP( flags = 'S', window = 65535, sport = RandShort(), dport = 502, options = [('MSS', 1360 ), ('NOP', 1), ('NOP', 1), ('SAckOK', '')])
synAck = sr1 ( ip / tcp )
# Send the ack
tcp.flags = 'A'
tcp.sport = synAck[TCP].dport
tcp.seq = synAck[TCP].ack
tcp.ack = synAck[TCP].seq + 1
tcp.options = ''
send( ip / tcp )
# Creates and sends the Modbus Read Holding Registers command packet
# Send the ack/push i.e. the request, receive the data i.e. the response
tcp.flags = 'AP'
adu = ModbusADU()
pdu = ModbusPDU03()
adu = adu / pdu
tcp = tcp / adu
data = sr1(( ip / tcp ), timeout = 2)
data.show()
# Acknowledges the response
# Ack the data response
# TODO: note, the 17 below should be replaced with a read packet length method...
tcp.flags = 'A'
tcp.seq = data[TCP].ack
tcp.ack = data[TCP] + 17
tcp.payload = ''
finAck = sr1( ip / tcp )
First, you have a bug in your code (which is present in the original version http://www.digitalbond.com/scadapedia/security-controls/scapy-modbus-extensions/), you need to add .seq there: tcp.ack = data[TCP].seq + 17.
As said in the comment, you could write tcp.ack = data[TCP].seq + len(data[TCP].payload).
Anyway it's generally useless to do the TCP stack's work for the kind of things you try to do.
I would do something like that:
from scapy import *
from modLib import *
import socket
sock = socket.socket()
sock.connect(("192.168.10.131", 502))
s = StreamSocket(sock, basecls=ModbusADU)
ans, unans = s.sr(ModbusADU()/ModbusPDU03())
ans.show()
Does this work better?

Resources