Looks like the problem has to do more with Python rather than Mininet.
I am trying to build the customer network topology using mininet, but stuck here.
When I run the below code, I am getting below error.
Traceback (most recent call last):
File "CustomTopo_Router2.py", line 37, in <module>
customTopo = NetworkTopo()
File "CustomTopo_Router2.py", line 28, in __init__
r1_obj = MininetRouter('122.1.1.1')
File "CustomTopo_Router2.py", line 12, in __init__
self.cmd('sysctl net.ipv4.ip_forward=1')
File "build/bdist.linux-x86_64/egg/mininet/node.py", line 353, in cmd
AttributeError: 'MininetRouter' object has no attribute 'name'
I dont even have any attribute name in MininetRouter class.
7 class MininetRouter ( Node ):
8
9 def __init__( self , loo_addr):
10
11 #Enable IP forwarding on the ROuter
12 self.cmd('sysctl net.ipv4.ip_forward=1')
13
14 # Create Loopback Interface and Assign Loopback Address to the Router
15 # All loopback addresses have mask 32
16 loo_config = 'ifconfig lo:1 ' + loo_addr + ' netmask 255.255.255.255 up'
17 self.cmd(loo_config)
18
19
20 class NetworkTopo( Topo ):
21
22 def __init__( self ):
23
24 # Initialize topology
25 Topo.__init__( self )
26
27 # Create a Router Object
28 r1_obj = MininetRouter('122.1.1.1')
29
30 # Add Router object to the topology
31 r1 = self.addNode('r1', r1_obj)
32
33
34
35 if __name__ == '__main__':
36
37 customTopo = NetworkTopo()
38
39 #Get handle to net to manage your topology
40 net = Mininet(topo=customTopo)
41
42 #start/deploy the Topology
43 net.start()
44
45 #Get Halt at Mininet CLI prompt
46 CLI(net)
47
48 #Destroy and stop the topology
49 net.stop()
50
51 # program ends here
What wrong am i doing here ? I have cross-chcked indentation.
PS : I am writing python code after couple of yrs now.
I made some modifications to the code, in order to make it work and more in line with the Mininet API. This should work, for what you are trying to do.
Be careful that I didn't put a controller because I don't have it installed, but you can use the Openflow Controller, RemoteController, etc.
I hope this can be useful to you.
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import Node
from mininet.log import setLogLevel, info
from mininet.cli import CLI
class MininetRouterModified( Node ):
"A Node with IP forwarding enabled."
def config( self, loo_addr, **params ):
super( MininetRouterModified, self).config( **params )
# Enable forwarding on the router
# Create Loopback Interface and Assign Loopback Address to the Router
# All loopback addresses have mask 32
loo_config = 'ifconfig lo:1 ' + loo_addr + ' netmask 255.255.255.255 up'
self.cmd(loo_config)
self.cmd( 'sysctl net.ipv4.ip_forward=1' )
def terminate( self ):
self.cmd( 'sysctl net.ipv4.ip_forward=0' )
super( MininetRouterModified, self ).terminate()
class NetworkTopo( Topo ):
def build(self, **_opts):
# Create a Router Object
#r1_obj = MininetRouter('122.1.1.1', name="r1")
# Add Router object to the topology
r1 = self.addNode(name='r1',loo_addr='122.1.1.1', cls=MininetRouterModified)
if __name__ == '__main__':
customTopo = NetworkTopo()
#Get handle to net to manage your topology
net = Mininet(topo=customTopo, controller=None)
#start/deploy the Topology
net.start()
#Get Halt at Mininet CLI prompt
CLI(net)
#Destroy and stop the topology
net.stop()
Related
Before I start, I have browsed the "similar questions" section before writing this and could not see one that matched a situation like mine. If one is found, please let me know and I will mark it as "answered" if it is in fact similar. I am a .net full stack developer by profession, i only recently started dabbling in Python and Electrical Engineering as a hobby.
I am creating an Automated Aquaponics Control system, a part of the project reads the temp of the grow bed media and with the input of various other sensors, recalculates the frequency at which the pump cycles to flood the bed. I am using a DS18B20 with Python3.9 and the W1ThermSensor v2.0.0a2 library. Here is the init and first of several functions for the sensor. I have the w1thermsensor as a property of the class instead of inheritance just during the initial testing, since it is easier to manipulate the code this way for me.
#!/usr/bin/env python3
from w1thermsensor import W1ThermSensor, Sensor, Unit
from datetime import datetime
import os
import numpy
import traceback
class DS18B20:
def __init__(self, min_temp=18, max_temp=26):
self.sensor = W1ThermSensor()
self.temp_string = "{dt} : Sensor: {id} :: {temp_c}C - {temp_f}F"
self.temp_c = 0.00
self.temp_f = 0.00
self.is_active = False
self.is_alert = False
self.min_temp = min_temp
self.max_temp = max_temp
self.values = [0.00, 0.00, 0.00, 0.00, 0.00]
self.value = 0.00
def start(self):
if self.sensor is None:
return False
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
# Set baseline for values Average
self.is_active = True
self.monitor()
self.values = [self.temp_c, self.temp_c, self.temp_c, self.temp_c, self.temp_c]
self.value = numpy.average(self.values)
This issue that I am running into is that it will have one of 3 issues:
Raises w1thermsensor.errors.NoSensorFoundError
Raises w1thermsensor.errors.SensorNotReadyError
Returns no value in the temp_c property after calling get_temperature()
I looked into this a bit more, If i load up the IDLE in Terminal using the 'sudo python3' command I can enter the following commands and it works no problem:
sudo python3
>>> from w1thermsensor import W1ThermSensor, Sensor
>>> import time
>>> temp_sensor = W1ThermSensor(Sensor.DS18B20)
>>> while True:
... print(str(round(temp_sensor.get_temperature()))
... time.sleep(2)
and it works without issue. I also try the 'cat' command
cd /sys/bus/w1/devices
cd 28-3c01d607414b
cat w1_slave
94 01 55 05 7f a5 81 66 5b : crc=5b YES
94 01 55 05 7f a5 81 66 5b t=25250
The stacktrace shows that it is throwing the Errors when it is calling the W1Termsensor() function in "init()". My question is, is it my code or implementation that is causing the issue, or is it something else. My sleep is set to 2 seconds in the hope that I am just catching it in the middle of an update. Any help would be a big help.
Addtional Info:
the DS18B20 is wired to a separate 5v power source, the capacitor it to stableize the voltage since there is a 5v relay and a LED array on the same 5v power rail of the power supply.
5v+ -------------+---------VCC------
| |
4.7 Kohm |
| |
GPIO4 ---------------------DQ = 1uf polCap
|
|
|
GND ----------------------GND-------
I have double-checked that I have 1-wire enabled.
I am trying to connect to my USB bar-code reader, but bump into a lack of rights to open it under Mac OS 10.14.6.
I am trying to use this library: https://github.com/vpelletier/python-libusb1 the lack of documentation is a bit annoying.
import usb1
VENDOR_ID = 8208
PRODUCT_ID = 30264
INTERFACE = 0
with usb1.USBContext() as context:
handle = context.openByVendorIDAndProductID(
VENDOR_ID,
PRODUCT_ID,
skip_on_error=False,
)
if handle is None:
# Device not present, or user is not allowed to access device.
print("no handle")
with handle.claimInterface(INTERFACE):
print("handle = ", handle)
# Do stuff with endpoints on claimed interface.
while True:
data = handle.bulkRead(ENDPOINT, BUFFER_SIZE)
# Process data...
Is there anyone having a clue on what to do ?
The error is :
USBErrorAccess Traceback (most recent call last)
<ipython-input-1-217d9879b039> in <module>
12 # Device not present, or user is not allowed to access device.
13 print("no handle")
---> 14 with handle.claimInterface(INTERFACE):
15 print("handle = ", handle)
16 # Do stuff with endpoints on claimed interface.
/Applications/anaconda3/lib/python3.7/site-packages/usb1/__init__.py in claimInterface(self, interface)
1307 """
1308 mayRaiseUSBError(
-> 1309 libusb1.libusb_claim_interface(self.__handle, interface),
1310 )
1311 return _ReleaseInterface(self, interface)
/Applications/anaconda3/lib/python3.7/site-packages/usb1/__init__.py in mayRaiseUSBError(value, __raiseUSBError)
131 ):
132 if value < 0:
--> 133 __raiseUSBError(value)
134 return value
135
/Applications/anaconda3/lib/python3.7/site-packages/usb1/__init__.py in raiseUSBError(value, __STATUS_TO_EXCEPTION_DICT, __USBError)
123 __USBError=USBError,
124 ):
--> 125 raise __STATUS_TO_EXCEPTION_DICT.get(value, __USBError)(value)
126
127 def mayRaiseUSBError(
USBErrorAccess: LIBUSB_ERROR_ACCESS [-3]
There is some hints :
seems like we should set up rights somewhere, but these pages are about ubuntu :
=> https://askubuntu.com/questions/978552/how-do-i-make-libusb-work-as-non-root
=> https://github.com/vpelletier/python-libusb1/issues/34
here are some things about Mac OS, but it is unclear to me :
=> IOCreatePlugInInterfaceForService returns mysterious error
=> OpenCV command line app can't access camera under macOS Mojave
I am trying to use modbus-tk to serially communicate with a device via Modbus RTU over a RS-485 network.
To understand how to use modbus-tk, I am trying to query:
Input register: Year of Manufacture
Register address: 0x7543 = 30019
Device: 1
Data type: 16-bit integer
Value = 2019 (verified using a free master modbus simulator).
Here is the code I use, based primarily on rtumaster_example.py.
Input:
#!/usr/bin/env python3
import time
from collections import namedtuple
from logging import Logger
from serial import Serial
from modbus_tk import modbus_rtu
import modbus_tk.defines as cst # cst = constants
from modbus_tk.utils import create_logger
PORT = "COM3"
SLAVE_NUM = 1
MODBUS_MASTER_TIMEOUT_SEC = 5.0
ModbusReg = namedtuple("ModbusInputRegister", ["name", "block_type", "address"])
year_of_manuf = ModbusReg(
"year of manufacture", cst.HOLDING_REGISTERS, 18
) # 0x7543 = 30019
logger = create_logger(name="console") # type: Logger
serial_ = Serial(PORT)
modbus_master = modbus_rtu.RtuMaster(serial_)
modbus_master.set_timeout(MODBUS_MASTER_TIMEOUT_SEC)
modbus_master.set_verbose(True)
time.sleep(2) # Per https://github.com/ljean/modbus-tk/issues/73#issuecomment-284800980
logger.info(
modbus_master.execute(
slave=SLAVE_NUM,
function_code=cst.READ_INPUT_REGISTERS,
starting_address=year_of_manuf.address,
)
)
Output:
2020-01-21 10:38:09,031 INFO modbus_rtu.__init__ MainThread RtuMaster COM3 is opened
2020-01-21 10:38:11,048 DEBUG modbus.execute MainThread -> 1-4-0-18-0-0-80-15
2020-01-21 10:38:11,077 DEBUG modbus.execute MainThread <- 1-132-3-3-1
---------------------------------------------------------------------------
ModbusError Traceback (most recent call last)
<ipython-input-2-9afaebcf3a35> in <module>
7 slave=SLAVE_NUM,
8 function_code=cst.READ_INPUT_REGISTERS,
----> 9 starting_address=year_of_manuf.address,
10 )
c:\path\to\venv\lib\site-packages\modbus_tk\utils.py in new(*args, **kwargs)
37 ret = fcn(*args, **kwargs)
38 except Exception as excpt:
---> 39 raise excpt
40 finally:
41 if threadsafe:
c:\path\to\venv\lib\site-packages\modbus_tk\utils.py in new(*args, **kwargs)
35 lock.acquire()
36 try:
---> 37 ret = fcn(*args, **kwargs)
38 except Exception as excpt:
39 raise excpt
c:\path\to\venv\lib\site-packages\modbus_tk\modbus.py in execute(self, slave, function_code, starting_address, quantity_of_x, output_value, data_format, expected_length)
312 # the slave has returned an error
313 exception_code = byte_2
--> 314 raise ModbusError(exception_code)
315 else:
316 if is_read_function:
ModbusError: Modbus Error: Exception code = 3
It looks like this exception is for if the slave has returned an error
What do you think I am doing wrong? I am new to this library.
What I Have Read
Can't connect to slave with Python's modbus_tk, I am using pyserial >= 3.1
And every other question under the modbus-tk tag, some posts in the Google Groups, and the repo's examples + README.md
Device Specifics
Device: SST Sensing's OXY-LC-485
Modbus RTU, 9600/8-N-1
User Guide (section 7.1.2.1 contains set of input registers)
Device is plugged into Windows machine that I run this Python script
Packages
I am using Python 3.6 on Windows 10.
pyserial==3.4
modbus-tk==1.1.0
**EDIT 1**
Per #Brits comment, I updated my registry addresses to be correct function codes and data frame addresses.
**EDIT 2**
Updated question since I am getting a different error after more correct library usage.
My problem was a lack of understanding of the Master.execute method. I did not realize that the quantity_of_x parameter needed to be made non-zero. A special thanks to #Brits for helping point out several key problems I had with my original code.
When the arg function_code == defines.READ_INPUT_REGISTERS, quantity_of_x means the amount of H (C type, unsigned short, length = 2-byte = 16-bit, source) to read (source code modbus.py, line 138).
Since the device's data type for the year_of_manuf register is 16-bit unsigned integer, the correct change was to add quantity_of_x=1 as an argument.
Functional Input:
logger.info(
modbus_master.execute(
slave=SLAVE_NUM,
function_code=cst.READ_INPUT_REGISTERS,
starting_address=year_of_manuf.address,
quantity_of_x=1,
)
)
Output:
2020-01-21 18:42:05,520 DEBUG modbus.execute MainThread -> 1-4-0-18-0-1-145-207
2020-01-21 18:42:05,560 DEBUG modbus.execute MainThread <- 1-4-2-7-227-250-137
2020-01-21 18:42:05,562 INFO <ipython-input-1-2d4d0280e33d>.<module> MainThread (2019,)
Basically, I pull a series of links from my database, and want to scrape them for specific links I'm looking for. I then re-feed those links into my link queue that my multiple QWebViews reference, and they continue to pull those down for processing/storage.
My issue is that as this runs for... say 200 or 500 links, it starts to use up more and more RAM.
I have exhaustively looked into this, using heapy, memory_profiler, and objgraph to figure out what's causing the memory leak... The python heap's objects stay about the the same in terms of amount AND size over time. This made me think the C++ objects weren't getting removed. Sure enough, using memory_profiler, the RAM only goes up when the self.load(self.url) lines of code are called. I've tried to fix this, but to no avail.
Code:
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebView, QWebSettings
from PyQt4.QtGui import QApplication
from lxml.etree import HTMLParser
# My functions
from util import dump_list2queue, parse_doc
class ThreadFlag:
def __init__(self, threads, jid, db):
self.threads = threads
self.job_id = jid
self.db_direct = db
self.xml_parser = HTMLParser()
class WebView(QWebView):
def __init__(self, thread_flag, id_no):
super(QWebView, self).__init__()
self.loadFinished.connect(self.handleLoadFinished)
self.settings().globalSettings().setAttribute(QWebSettings.AutoLoadImages, False)
# This is actually a dict with a few additional details about the url we want to pull
self.url = None
# doing one instance of this to avoid memory leaks
self.qurl = QUrl()
# id of the webview instance
self.id = id_no
# Status webview instance, green mean it isn't working and yellow means it is.
self.status = 'GREEN'
# Reference to a single universal object all the webview instances can see.
self.thread_flag = thread_flag
def handleLoadFinished(self):
try:
self.processCurrentPage()
except Exception as e:
print e
self.status = 'GREEN'
if not self.fetchNext():
# We're finished!
self.loadFinished.disconnect()
self.stop()
else:
# We're not finished! Do next url.
self.qurl.setUrl(self.url['url'])
self.load(self.qurl)
def processCurrentPage(self):
self.frame = str(self.page().mainFrame().toHtml().toUtf8())
# This is the case for the initial web pages I want to gather links from.
if 'name' in self.url:
# Parse html string for links I'm looking for.
new_links = parse_doc(self.thread_flag.xml_parser, self.url, self.frame)
if len(new_links) == 0: return 0
fkid = self.url['pkid']
new_links = map(lambda x: (fkid, x['title'],x['url'], self.thread_flag.job_id), new_links)
# Post links to database, db de-dupes and then repull ones that made it.
self.thread_flag.db_direct.post_links(new_links)
added_links = self.thread_flag.db_direct.get_links(self.thread_flag.job_id,fkid)
# Add the pulled links to central queue all the qwebviews pull from
dump_list2queue(added_links, self._urls)
del added_links
else:
# Process one of the links I pulled from the initial set of data that was originally in the queue.
print "Processing target link!"
# Get next url from the universal queue!
def fetchNext(self):
if self._urls and self._urls.empty():
self.status = 'GREEN'
return False
else:
self.status = 'YELLOW'
self.url = self._urls.get()
return True
def start(self, urls):
# This is where the reference to the universal queue gets made.
self._urls = urls
if self.fetchNext():
self.qurl.setUrl(self.url['url'])
self.load(self.qurl)
# uq = central url queue shared between webview instances
# ta = array of webview objects
# tf - thread flag (basically just a custom universal object that all the webviews can access).
# This main "program" is started by another script elsewhere.
def main_program(uq, ta, tf):
app = QApplication([])
webviews = ta
threadflag = tf
tf.app = app
print "Beginning the multiple async web calls..."
# Create n "threads" (really just webviews) that each will make asynchronous calls.
for n in range(0,threadflag.threads):
webviews.append(WebView(threadflag, n+1))
webviews[n].start(uq)
app.exec_()
Here's what my memory tools say (they're all about constant through the whole program)
RAM: resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024
2491(MB)
Objgraph most common types:
methoddescriptor 9959
function 8342
weakref 6440
tuple 6418
dict 4982
wrapper_descriptor 4380
getset_descriptor 2314
list 1890
method_descriptor 1445
builtin_function_or_method 1298
Heapy:
Partition of a set of 9879 objects. Total size = 1510000 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 2646 27 445216 29 445216 29 str
1 563 6 262088 17 707304 47 dict (no owner)
2 2267 23 199496 13 906800 60 __builtin__.weakref
3 2381 24 179128 12 1085928 72 tuple
4 212 2 107744 7 1193672 79 dict of guppy.etc.Glue.Interface
5 50 1 52400 3 1246072 83 dict of guppy.etc.Glue.Share
6 121 1 40200 3 1286272 85 list
7 116 1 32480 2 1318752 87 dict of guppy.etc.Glue.Owner
8 240 2 30720 2 1349472 89 types.CodeType
9 42 0 24816 2 1374288 91 dict of class
Your program is indeed experiencing growth due to C++ code, but it is not an actual leak in terms of the creation of objects that are no longer referenced. What is happening, at least in part, is that your QWebView holds a QWebPage which holds a QWebHistory(). Each time you call self.load the history is getting a bit longer.
Note that QWebHistory has a clear() function.
Documentation is available: http://pyqt.sourceforge.net/Docs/PyQt4/qwebview.html#history
I wrote an initiator using the Python API for QuickFIX 1.13.3.
It simply sends a message of type TradeCaptureReport (code: AE) to an acceptor.
I should receive a TradeCaptureReportAck (indeed, I receive it if I use another client), but nothing comes back.
Using Wireshark I could see that logon and logout are performed correctly and the heartbeat is kept properly as well.
The Application I have written is defined as follows:
import sys
import time
import thread
import quickfix as fix
import quickfix44 as fix44
from datetime import datetime
class Application (fix.Application):
orderID = 0
execID = 0
tradeID = 0
global settings
def onCreate (self, sessionID):
self.sessionID = sessionID
print ("Application created - session: " + sessionID.toString ())
def onLogon (self, sessionID):
print ("Logon")
def onLogout (self, sessionID):
print ("Logout")
def onMessage (self, message, sessionID):
print (message)
def toAdmin (self, message, sessionID):
msgType = fix.MsgType ()
message.getHeader ().getField (msgType)
if (msgType.getValue () == fix.MsgType_Logon):
message.setField (fix.Password (settings.get (self.sessionID).getString ("Password")))
message.setField (fix.ResetSeqNumFlag (True))
def fromAdmin (self, message, sessionID):
pass
def toApp (self, message, sessionID):
pass
def fromApp (self, message, sessionID):
pass
def genOrderID (self):
self.orderID += 1
return repr (self.orderID)
def genTradeReportID (self):
self.tradeID += 1
return repr (self.tradeID)
def genExecID (self):
self.execID += 1
return repr (self.execID)
def run (self):
time.sleep (5)
self.queryEnterOrder ()
time.sleep (5)
def queryEnterOrder (self):
print ("\nTradeCaptureReport (AE)\n")
trade = fix.Message ()
trade.getHeader ().setField (fix.BeginString (fix.BeginString_FIX44))
trade.getHeader ().setField (fix.MsgType (fix.MsgType_TradeCaptureReport))
trade.setField (fix.TradeReportTransType (fix.TradeReportTransType_NEW)) # 487
trade.setField (fix.TradeReportID (self.genTradeReportID ())) # 571
trade.setField (fix.TrdSubType (4)) # 829
trade.setField (fix.SecondaryTrdType (2)) # 855
trade.setField (fix.Symbol ("MYSYMBOL")) # 55
trade.setField (fix.LastQty (22)) # 32
trade.setField (fix.LastPx (21.12)) # 31
trade.setField (fix.TradeDate ((datetime.now ().strftime ("%Y%m%d")))) # 75
trade.setField (fix.TransactTime ((datetime.now ().strftime ("%Y%m%d-%H:%M:%S.%f"))[:-3])) # 60
trade.setField (fix.PreviouslyReported (False)) # 570
group = fix44.TradeCaptureReport ().NoSides ()
group.setField (fix.Side (fix.Side_SELL)) # 54
group.setField (fix.OrderID (self.genOrderID ())) # 37
group.setField (fix.NoPartyIDs (1)) # 453
group.setField (fix.PartyIDSource (fix.PartyIDSource_PROPRIETARY_CUSTOM_CODE)) # 447
group.setField (fix.PartyID ("CLEARING")) # 448
group.setField (fix.PartyRole (fix.PartyRole_CLEARING_ACCOUNT)) # 452
trade.addGroup (group)
group.setField (fix.Side (fix.Side_BUY)) # 54
group.setField (fix.OrderID (self.genOrderID ())) # 37
group.setField (fix.NoPartyIDs (1)) # 453
group.setField (fix.PartyIDSource (fix.PartyIDSource_PROPRIETARY_CUSTOM_CODE)) # 447
group.setField (fix.PartyID ("CLEARING")) # 448
group.setField (fix.PartyRole (fix.PartyRole_CLEARING_ACCOUNT)) # 452
trade.addGroup (group)
fix.Session.sendToTarget (trade, self.sessionID)
Which is run thanks to the following snippet:
file = sys.argv[1]
settings = fix.SessionSettings (file)
application = Application ()
storeFactory = fix.FileStoreFactory (settings)
initiator = fix.SocketInitiator (application, storeFactory, settings)
initiator.start ()
application.run ()
initiator.stop ()
Update
The exchange of messages goeas as follows (I = Initiator, A = Acceptor):
1. I ---------- LOGON -----------> A
2. I <--------- LOGON ------------ A
3. I ---- TradeCaptureReport ----> A
4. I ---------- LOGOFF ----------> A
5. I <--------- LOGOFF ----------- A
As you can spot, between 3. and 4. a message of type TradeCaptureReportAck is missing.
Any hint is most welcome!
Try implementing your fromAdmin and fromApp method, you should be seeing your return FIX messages here. Check if your TradeCaptureReportAck reaches here and confirm they follow the same calls as logon, logout and heartbeat. And implement your onMessage method, or check if you receive any FIX message here. This should be your place where you should be seeing the ACK return message.
If your message sequence number is not our of sync, then they never sent the act you are looking for! Instead of logging off, you should at least wait around for a heartbeat to check the sequence number before logging off.