Module ddCommunication.protocols.DDCOMM32To64BitBridge.PythonClient.Subcontrolcard
Expand source code
import socket
from .Protobuf.PacketType_pb2 import PacketType
from .Protobuf.ConnectNodeRequest_pb2 import ConnectNodeRequest
from .Client import Client
import subprocess
import os
import time
import threading
import logging
LOGGER = logging.getLogger(__name__)
reconnect_lock = threading.Lock()
def try_reconnect_on_error(func):
def i(*args, **kwargs):
reconnect_lock.acquire()
try:
res = func(*args, **kwargs)
reconnect_lock.release()
return res
except Exception as ex:
try:
args[0].reconnect()
except OSError as os:
reconnect_lock.release()
raise os
except Exception as e:
pass
reconnect_lock.release()
raise ex
return i
class Subcontrolcard(object):
def __init__(self):
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client = Client(lambda x: self.connection.recv(
x), lambda x: self.connection.send(x), lambda: True)
self.basePort = 25540
@try_reconnect_on_error
def get_drive_info(self, param_id):
return self.client.get_drive_info(param_id)
@try_reconnect_on_error
def get_drive(self, param_id, index=0, textinfo="None"):
return self.client.get_drive(param_id, index)
@try_reconnect_on_error
def set_drive(self, param_id, value, index=0, textinfo="None"):
return self.client.set_drive(param_id, value, index)
def set_bootmode(self):
self.set_drive(1429, 0x31700553)
self.set_drive(1422, 3) # BOOTMODE
try:
self.set_drive(1429, 0x700DBABE)
except ConnectionError as error:
self.disconnect_drive()
def __try_connect_ports(self, port):
self._open_process(port)
try:
self.connection.connect(("127.0.0.1", port))
except Exception as ex:
self._close_process()
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client = Client(lambda x: self.connection.recv(
x), lambda x: self.connection.send(x), lambda: True)
return False
return True
def reconnect(self):
self.connection.close()
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.client = Client(lambda x: self.connection.recv(
x), lambda x: self.connection.send(x), lambda: True)
self.connection.connect(("127.0.0.1", self.basePort))
connectNode = ConnectNodeRequest()
connectNode.BusName = self.field_bus
connectNode.NodeName = "1"
logging.debug("Sending connect request")
self.client.transcieve(PacketType.ConnectNode, connectNode)
def connect_drive(self, field_bus):
if hasattr(self, "process") and self.process != None:
raise Exception(
"You have not called disconnect drive for the current process")
Success = False
logging.debug("Trying to start process")
for offset in range(20):
if self.__try_connect_ports(self.basePort + offset):
Success = True
self.basePort = self.basePort + offset
logging.debug("Successfully connected to port " +
str(self.basePort))
break
if not Success:
return False
self.field_bus = field_bus
connectNode = ConnectNodeRequest()
connectNode.BusName = field_bus
connectNode.NodeName = "1"
logging.debug("Sending connect request")
self.client.transcieve(PacketType.ConnectNode, connectNode)
return True
def disconnect_drive(self):
logging.debug("Closing connection")
self.connection.close()
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
logging.debug("Reseting socket")
self.client = Client(lambda x: self.connection.recv(
x), lambda x: self.connection.send(x), lambda: True)
# close the process
self._close_process()
import time
time.sleep(0.5)
return True
def _close_process(self):
if hasattr(self, "process") and self.process != None:
logging.debug("Closing process")
self.process.kill()
self.process = None
# os.system("taskkill /im Protocol.Reference.Server.CMD.exe /f /fi \"STATUS eq RUNNING\" > nul")
def _open_process(self, port=25540):
# This is mainly here so that a "not responding" dialog window wont appear if a crash happens
import ctypes
SEM_NOGPFAULTERRORBOX = 0x0002
ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX)
CREATE_NO_WINDOW = 0x08000000
subprocess_flags = CREATE_NO_WINDOW
self.process = subprocess.Popen([os.path.dirname(__file__) + "\\Server\\Protocol.Reference.Server.CMD.exe", str(port)],
shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
stdin=subprocess.DEVNULL, creationflags=subprocess_flags)
if __name__ == "__main__":
cl = Subcontrolcard()
cl.connect_drive("USB 1")
# cl.set_bootmode()
for i in range(20):
get = cl.get_drive(1)
# for i in range(4094):
# try:
# res = cl.get_drive(i+1)
# cl.set_drive(i+1,res)
# print(str(i+1) + ":" + str(res))
# except Exception as e:
# print("Failed reading: " + str(i+1))
# cl.disconnect_drive()
# cl.connect_drive("USB 1")
# # cl.disconnect_drive()
cl.disconnect_drive()
Functions
def try_reconnect_on_error(func)
-
Expand source code
def try_reconnect_on_error(func): def i(*args, **kwargs): reconnect_lock.acquire() try: res = func(*args, **kwargs) reconnect_lock.release() return res except Exception as ex: try: args[0].reconnect() except OSError as os: reconnect_lock.release() raise os except Exception as e: pass reconnect_lock.release() raise ex return i
Classes
class ConnectNodeRequest (**kwargs)
-
Abstract base class for protocol messages.
Protocol message classes are almost always generated by the protocol compiler. These generated types subclass Message and implement the methods shown below.
TODO(robinson): Link to an HTML document here.
TODO(robinson): Document that instances of this class will also have an Extensions attribute with getitem and setitem. Again, not sure how to best convey this.
TODO(robinson): Document that the class must also have a static RegisterExtension(extension_field) method. Not sure how to best express at this point.
Ancestors
- google.protobuf.message.Message
Class variables
var BUSNAME_FIELD_NUMBER
var DESCRIPTOR
var NODENAME_FIELD_NUMBER
Static methods
def FromString(s)
-
Expand source code
def FromString(s): message = cls() message.MergeFromString(s) return message
def RegisterExtension(extension_handle)
-
Expand source code
def RegisterExtension(extension_handle): extension_handle.containing_type = cls.DESCRIPTOR # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. # pylint: disable=protected-access cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle) _AttachFieldHelpers(cls, extension_handle)
Instance variables
var BusName
-
Getter for BusName.
Expand source code
def getter(self): # TODO(protobuf-team): This may be broken since there may not be # default_value. Combine with has_default_value somehow. return self._fields.get(field, default_value)
var NodeName
-
Getter for NodeName.
Expand source code
def getter(self): # TODO(protobuf-team): This may be broken since there may not be # default_value. Combine with has_default_value somehow. return self._fields.get(field, default_value)
Methods
def ByteSize(self)
-
Expand source code
def ByteSize(self): if not self._cached_byte_size_dirty: return self._cached_byte_size size = 0 descriptor = self.DESCRIPTOR if descriptor.GetOptions().map_entry: # Fields of map entry should always be serialized. size = descriptor.fields_by_name['key']._sizer(self.key) size += descriptor.fields_by_name['value']._sizer(self.value) else: for field_descriptor, field_value in self.ListFields(): size += field_descriptor._sizer(field_value) for tag_bytes, value_bytes in self._unknown_fields: size += len(tag_bytes) + len(value_bytes) self._cached_byte_size = size self._cached_byte_size_dirty = False self._listener_for_children.dirty = False return size
def Clear(self)
-
Expand source code
def _Clear(self): # Clear fields. self._fields = {} self._unknown_fields = () # pylint: disable=protected-access if self._unknown_field_set is not None: self._unknown_field_set._clear() self._unknown_field_set = None self._oneofs = {} self._Modified()
def ClearField(self, field_name)
-
Expand source code
def ClearField(self, field_name): try: field = message_descriptor.fields_by_name[field_name] except KeyError: try: field = message_descriptor.oneofs_by_name[field_name] if field in self._oneofs: field = self._oneofs[field] else: return except KeyError: raise ValueError('Protocol message %s has no "%s" field.' % (message_descriptor.name, field_name)) if field in self._fields: # To match the C++ implementation, we need to invalidate iterators # for map fields when ClearField() happens. if hasattr(self._fields[field], 'InvalidateIterators'): self._fields[field].InvalidateIterators() # Note: If the field is a sub-message, its listener will still point # at us. That's fine, because the worst than can happen is that it # will call _Modified() and invalidate our byte size. Big deal. del self._fields[field] if self._oneofs.get(field.containing_oneof, None) is field: del self._oneofs[field.containing_oneof] # Always call _Modified() -- even if nothing was changed, this is # a mutating method, and thus calling it should cause the field to become # present in the parent message. self._Modified()
def DiscardUnknownFields(self)
-
Expand source code
def _DiscardUnknownFields(self): self._unknown_fields = [] self._unknown_field_set = None # pylint: disable=protected-access for field, value in self.ListFields(): if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: if _IsMapField(field): if _IsMessageMapField(field): for key in value: value[key].DiscardUnknownFields() elif field.label == _FieldDescriptor.LABEL_REPEATED: for sub_message in value: sub_message.DiscardUnknownFields() else: value.DiscardUnknownFields()
def FindInitializationErrors(self)
-
Finds required fields which are not initialized.
Returns
A list of strings. Each string is a path to an uninitialized field from the top-level message, e.g. "foo.bar[5].baz".
Expand source code
def FindInitializationErrors(self): """Finds required fields which are not initialized. Returns: A list of strings. Each string is a path to an uninitialized field from the top-level message, e.g. "foo.bar[5].baz". """ errors = [] # simplify things for field in required_fields: if not self.HasField(field.name): errors.append(field.name) for field, value in self.ListFields(): if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: if field.is_extension: name = '(%s)' % field.full_name else: name = field.name if _IsMapField(field): if _IsMessageMapField(field): for key in value: element = value[key] prefix = '%s[%s].' % (name, key) sub_errors = element.FindInitializationErrors() errors += [prefix + error for error in sub_errors] else: # ScalarMaps can't have any initialization errors. pass elif field.label == _FieldDescriptor.LABEL_REPEATED: for i in range(len(value)): element = value[i] prefix = '%s[%d].' % (name, i) sub_errors = element.FindInitializationErrors() errors += [prefix + error for error in sub_errors] else: prefix = name + '.' sub_errors = value.FindInitializationErrors() errors += [prefix + error for error in sub_errors] return errors
def HasField(self, field_name)
-
Expand source code
def HasField(self, field_name): try: field = hassable_fields[field_name] except KeyError: raise ValueError(error_msg % (message_descriptor.full_name, field_name)) if isinstance(field, descriptor_mod.OneofDescriptor): try: return HasField(self, self._oneofs[field].name) except KeyError: return False else: if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: value = self._fields.get(field) return value is not None and value._is_present_in_parent else: return field in self._fields
def IsInitialized(self, errors=None)
-
Checks if all required fields of a message are set.
Args
errors
- A list which, if provided, will be populated with the field paths of all missing required fields.
Returns
True iff the specified message has all required fields set.
Expand source code
def IsInitialized(self, errors=None): """Checks if all required fields of a message are set. Args: errors: A list which, if provided, will be populated with the field paths of all missing required fields. Returns: True iff the specified message has all required fields set. """ # Performance is critical so we avoid HasField() and ListFields(). for field in required_fields: if (field not in self._fields or (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and not self._fields[field]._is_present_in_parent)): if errors is not None: errors.extend(self.FindInitializationErrors()) return False for field, value in list(self._fields.items()): # dict can change size! if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: if field.label == _FieldDescriptor.LABEL_REPEATED: if (field.message_type.has_options and field.message_type.GetOptions().map_entry): continue for element in value: if not element.IsInitialized(): if errors is not None: errors.extend(self.FindInitializationErrors()) return False elif value._is_present_in_parent and not value.IsInitialized(): if errors is not None: errors.extend(self.FindInitializationErrors()) return False return True
def ListFields(self)
-
Expand source code
def ListFields(self): all_fields = [item for item in self._fields.items() if _IsPresent(item)] all_fields.sort(key = lambda item: item[0].number) return all_fields
def MergeFrom(self, msg)
-
Expand source code
def MergeFrom(self, msg): if not isinstance(msg, cls): raise TypeError( 'Parameter to MergeFrom() must be instance of same class: ' 'expected %s got %s.' % (cls.__name__, msg.__class__.__name__)) assert msg is not self self._Modified() fields = self._fields for field, value in msg._fields.items(): if field.label == LABEL_REPEATED: field_value = fields.get(field) if field_value is None: # Construct a new object to represent this field. field_value = field._default_constructor(self) fields[field] = field_value field_value.MergeFrom(value) elif field.cpp_type == CPPTYPE_MESSAGE: if value._is_present_in_parent: field_value = fields.get(field) if field_value is None: # Construct a new object to represent this field. field_value = field._default_constructor(self) fields[field] = field_value field_value.MergeFrom(value) else: self._fields[field] = value if field.containing_oneof: self._UpdateOneofState(field) if msg._unknown_fields: if not self._unknown_fields: self._unknown_fields = [] self._unknown_fields.extend(msg._unknown_fields) # pylint: disable=protected-access if self._unknown_field_set is None: self._unknown_field_set = containers.UnknownFieldSet() self._unknown_field_set._extend(msg._unknown_field_set)
def MergeFromString(self, serialized)
-
Expand source code
def MergeFromString(self, serialized): if isinstance(serialized, memoryview) and six.PY2: raise TypeError( 'memoryview not supported in Python 2 with the pure Python proto ' 'implementation: this is to maintain compatibility with the C++ ' 'implementation') serialized = memoryview(serialized) length = len(serialized) try: if self._InternalParse(serialized, 0, length) != length: # The only reason _InternalParse would return early is if it # encountered an end-group tag. raise message_mod.DecodeError('Unexpected end-group tag.') except (IndexError, TypeError): # Now ord(buf[p:p+1]) == ord('') gets TypeError. raise message_mod.DecodeError('Truncated message.') except struct.error as e: raise message_mod.DecodeError(e) return length # Return this for legacy reasons.
def SerializePartialToString(self, **kwargs)
-
Expand source code
def SerializePartialToString(self, **kwargs): out = BytesIO() self._InternalSerialize(out.write, **kwargs) return out.getvalue()
def SerializeToString(self, **kwargs)
-
Expand source code
def SerializeToString(self, **kwargs): # Check if the message has all of its required fields set. if not self.IsInitialized(): raise message_mod.EncodeError( 'Message %s is missing required fields: %s' % ( self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors()))) return self.SerializePartialToString(**kwargs)
def SetInParent(self)
-
Sets the _cached_byte_size_dirty bit to true, and propagates this to our listener iff this was a state change.
Expand source code
def Modified(self): """Sets the _cached_byte_size_dirty bit to true, and propagates this to our listener iff this was a state change. """ # Note: Some callers check _cached_byte_size_dirty before calling # _Modified() as an extra optimization. So, if this method is ever # changed such that it does stuff even when _cached_byte_size_dirty is # already true, the callers need to be updated. if not self._cached_byte_size_dirty: self._cached_byte_size_dirty = True self._listener_for_children.dirty = True self._is_present_in_parent = True self._listener.Modified()
def UnknownFields(self)
-
Expand source code
def _UnknownFields(self): if self._unknown_field_set is None: # pylint: disable=protected-access # pylint: disable=protected-access self._unknown_field_set = containers.UnknownFieldSet() return self._unknown_field_set # pylint: disable=protected-access
def WhichOneof(self, oneof_name)
-
Returns the name of the currently set field inside a oneof, or None.
Expand source code
def WhichOneof(self, oneof_name): """Returns the name of the currently set field inside a oneof, or None.""" try: field = message_descriptor.oneofs_by_name[oneof_name] except KeyError: raise ValueError( 'Protocol message has no oneof "%s" field.' % oneof_name) nested_field = self._oneofs.get(field, None) if nested_field is not None and self.HasField(nested_field.name): return nested_field.name else: return None
class Subcontrolcard
-
Expand source code
class Subcontrolcard(object): def __init__(self): self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client = Client(lambda x: self.connection.recv( x), lambda x: self.connection.send(x), lambda: True) self.basePort = 25540 @try_reconnect_on_error def get_drive_info(self, param_id): return self.client.get_drive_info(param_id) @try_reconnect_on_error def get_drive(self, param_id, index=0, textinfo="None"): return self.client.get_drive(param_id, index) @try_reconnect_on_error def set_drive(self, param_id, value, index=0, textinfo="None"): return self.client.set_drive(param_id, value, index) def set_bootmode(self): self.set_drive(1429, 0x31700553) self.set_drive(1422, 3) # BOOTMODE try: self.set_drive(1429, 0x700DBABE) except ConnectionError as error: self.disconnect_drive() def __try_connect_ports(self, port): self._open_process(port) try: self.connection.connect(("127.0.0.1", port)) except Exception as ex: self._close_process() self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client = Client(lambda x: self.connection.recv( x), lambda x: self.connection.send(x), lambda: True) return False return True def reconnect(self): self.connection.close() self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client = Client(lambda x: self.connection.recv( x), lambda x: self.connection.send(x), lambda: True) self.connection.connect(("127.0.0.1", self.basePort)) connectNode = ConnectNodeRequest() connectNode.BusName = self.field_bus connectNode.NodeName = "1" logging.debug("Sending connect request") self.client.transcieve(PacketType.ConnectNode, connectNode) def connect_drive(self, field_bus): if hasattr(self, "process") and self.process != None: raise Exception( "You have not called disconnect drive for the current process") Success = False logging.debug("Trying to start process") for offset in range(20): if self.__try_connect_ports(self.basePort + offset): Success = True self.basePort = self.basePort + offset logging.debug("Successfully connected to port " + str(self.basePort)) break if not Success: return False self.field_bus = field_bus connectNode = ConnectNodeRequest() connectNode.BusName = field_bus connectNode.NodeName = "1" logging.debug("Sending connect request") self.client.transcieve(PacketType.ConnectNode, connectNode) return True def disconnect_drive(self): logging.debug("Closing connection") self.connection.close() self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logging.debug("Reseting socket") self.client = Client(lambda x: self.connection.recv( x), lambda x: self.connection.send(x), lambda: True) # close the process self._close_process() import time time.sleep(0.5) return True def _close_process(self): if hasattr(self, "process") and self.process != None: logging.debug("Closing process") self.process.kill() self.process = None # os.system("taskkill /im Protocol.Reference.Server.CMD.exe /f /fi \"STATUS eq RUNNING\" > nul") def _open_process(self, port=25540): # This is mainly here so that a "not responding" dialog window wont appear if a crash happens import ctypes SEM_NOGPFAULTERRORBOX = 0x0002 ctypes.windll.kernel32.SetErrorMode(SEM_NOGPFAULTERRORBOX) CREATE_NO_WINDOW = 0x08000000 subprocess_flags = CREATE_NO_WINDOW self.process = subprocess.Popen([os.path.dirname(__file__) + "\\Server\\Protocol.Reference.Server.CMD.exe", str(port)], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL, creationflags=subprocess_flags)
Methods
def connect_drive(self, field_bus)
-
Expand source code
def connect_drive(self, field_bus): if hasattr(self, "process") and self.process != None: raise Exception( "You have not called disconnect drive for the current process") Success = False logging.debug("Trying to start process") for offset in range(20): if self.__try_connect_ports(self.basePort + offset): Success = True self.basePort = self.basePort + offset logging.debug("Successfully connected to port " + str(self.basePort)) break if not Success: return False self.field_bus = field_bus connectNode = ConnectNodeRequest() connectNode.BusName = field_bus connectNode.NodeName = "1" logging.debug("Sending connect request") self.client.transcieve(PacketType.ConnectNode, connectNode) return True
def disconnect_drive(self)
-
Expand source code
def disconnect_drive(self): logging.debug("Closing connection") self.connection.close() self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logging.debug("Reseting socket") self.client = Client(lambda x: self.connection.recv( x), lambda x: self.connection.send(x), lambda: True) # close the process self._close_process() import time time.sleep(0.5) return True
def get_drive(*args, **kwargs)
-
Expand source code
def i(*args, **kwargs): reconnect_lock.acquire() try: res = func(*args, **kwargs) reconnect_lock.release() return res except Exception as ex: try: args[0].reconnect() except OSError as os: reconnect_lock.release() raise os except Exception as e: pass reconnect_lock.release() raise ex
def get_drive_info(*args, **kwargs)
-
Expand source code
def i(*args, **kwargs): reconnect_lock.acquire() try: res = func(*args, **kwargs) reconnect_lock.release() return res except Exception as ex: try: args[0].reconnect() except OSError as os: reconnect_lock.release() raise os except Exception as e: pass reconnect_lock.release() raise ex
def reconnect(self)
-
Expand source code
def reconnect(self): self.connection.close() self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client = Client(lambda x: self.connection.recv( x), lambda x: self.connection.send(x), lambda: True) self.connection.connect(("127.0.0.1", self.basePort)) connectNode = ConnectNodeRequest() connectNode.BusName = self.field_bus connectNode.NodeName = "1" logging.debug("Sending connect request") self.client.transcieve(PacketType.ConnectNode, connectNode)
def set_bootmode(self)
-
Expand source code
def set_bootmode(self): self.set_drive(1429, 0x31700553) self.set_drive(1422, 3) # BOOTMODE try: self.set_drive(1429, 0x700DBABE) except ConnectionError as error: self.disconnect_drive()
def set_drive(*args, **kwargs)
-
Expand source code
def i(*args, **kwargs): reconnect_lock.acquire() try: res = func(*args, **kwargs) reconnect_lock.release() return res except Exception as ex: try: args[0].reconnect() except OSError as os: reconnect_lock.release() raise os except Exception as e: pass reconnect_lock.release() raise ex