Commits

Tino de Bruijn committed acdbe82

Factored out bytes utility functions to util. Also fixed the way the firmwarestring is read. Thanks to nickraptis

Comments (0)

Files changed (3)

pyfirmata/pyfirmata.py

 import serial
 import inspect
 import time
-from boards import BOARDS
+from util import two_byte_iter_to_str
 
 # Message command bytes - straight from Firmata.h
 DIGITAL_MESSAGE = 0x90      # send data for a digital pin
         
     def send_as_two_bytes(self, val):
         self.sp.write(chr(val % 128) + chr(val >> 7))
-        
-    def received_as_two_bytes(self, bytes):
-        lsb, msb = bytes
-        return msb << 7 | lsb
-        
+
     def setup_layout(self, board_layout):
         """
         Setup the Pin instances based on the given board-layout. Maybe it will
         major = data[0]
         minor = data[1]
         self.firmata_version = (major, minor)
-        self.firmware = ''.join([chr(x) for x in data[2:]]) # TODO this is more complicated, values is send as 7 bit bytes
+        self.firmware = two_byte_iter_to_str(data[2:])
 
 class Port(object):
     """ An 8-bit port on the board """

pyfirmata/util.py

                     pass
                 raise
                 
-def to_7_bits(integer):
+def to_two_bytes(integer):
     """
     Breaks an integer into two 7 bit bytes.
     
     >>> for i in range(32768):
-    ...     val = to_7_bits(i)
+    ...     val = to_two_bytes(i)
     ...     assert len(val) == 2
     ...
-    >>> to_7_bits(32767)
+    >>> to_two_bytes(32767)
     ('\\x7f', '\\xff')
-    >>> to_7_bits(32768)
+    >>> to_two_bytes(32768)
     Traceback (most recent call last):
         ...
     ValueError: Can't handle values bigger than 32767 (max for 2 bits)
     if integer > 32767:
         raise ValueError, "Can't handle values bigger than 32767 (max for 2 bits)"
     return chr(integer % 128), chr(integer >> 7)
+    
+def from_two_bytes(bytes):
+    """
+    Return an integer from two 7 bit bytes.
+    
+    >>> for i in range(32766, 32768):
+    ...     val = to_two_bytes(i)
+    ...     ret = from_two_bytes(val)
+    ...     assert ret == i
+    ...
+    >>> from_two_bytes(('\\xff', '\\xff'))
+    32767
+    >>> from_two_bytes(('\\x7f', '\\xff'))
+    32767
+    """
+    lsb, msb = bytes
+    try:
+        # Usually bytes have been converted to integers with ord already
+        return msb << 7 | lsb
+    except TypeError:
+        # But add this for easy testing
+        # One of them can be a string, or both
+        try:
+            lsb = ord(lsb)
+        except TypeError:
+            pass
+        try:
+            msb = ord(msb)
+        except TypeError:
+            pass
+        return msb << 7 | lsb
+    
+def two_byte_iter_to_str(bytes):
+    """
+    Return a string made from a list of two byte chars.
+    
+    >>> string, s = 'StandardFirmata', []
+    >>> for i in string:
+    ...   s.append(i)
+    ...   s.append('\\x00')
+    >>> two_byte_iter_to_str(s)
+    'StandardFirmata'
+    
+    >>> string, s = 'StandardFirmata', []
+    >>> for i in string:
+    ...   s.append(ord(i))
+    ...   s.append(ord('\\x00'))
+    >>> two_byte_iter_to_str(s)
+    'StandardFirmata'
+    """
+    bytes = list(bytes)
+    chars = []
+    while bytes:
+        lsb = bytes.pop(0)
+        try:
+            msb = bytes.pop(0)
+        except IndexError:
+            msb = 0x00
+        chars.append(chr(from_two_bytes((lsb, msb))))
+    return ''.join(chars)
+    
+def str_to_two_byte_iter(string):
+    """
+    Return a iter consisting of two byte chars from a string.
+    
+    >>> string, iter = 'StandardFirmata', []
+    >>> for i in string:
+    ...   iter.append(i)
+    ...   iter.append('\\x00')
+    >>> assert iter == str_to_two_byte_iter(string)
+     """
+    bytes = []
+    for char in string:
+        bytes += list(to_two_bytes(ord(char)))
+    return bytes
 
 def break_to_bytes(value):
     """
 import unittest
 import serial
-import time
 import pyfirmata
 from pyfirmata import mockup
 from pyfirmata.boards import BOARDS
-from pyfirmata.util import to_7_bits
+from pyfirmata.util import str_to_two_byte_iter
 
 # Messages todo left:
 
         
     def test_handle_report_firmware(self):
         self.assertEqual(self.board.firmware, None)
-        data = [2, 1] + [ord(x) for x in 'Firmware_name']
+        data = [2, 1] + str_to_two_byte_iter('Firmware_name')
         self.board._handle_report_firmware(*data)
         self.assertEqual(self.board.firmware, 'Firmware_name')
         self.assertEqual(self.board.firmata_version, (2, 1))
         msg = [chr(pyfirmata.START_SYSEX), 
                chr(pyfirmata.REPORT_FIRMWARE), 
                chr(2), 
-               chr(1)] + [i for i in 'Firmware_name'] + \
+               chr(1)] + str_to_two_byte_iter('Firmware_name') + \
               [chr(pyfirmata.END_SYSEX)]
         self.board.sp.write(msg)
         self.board.iterate()
         self.assert_serial(*sysex)
         
     def test_receive_sysex_message(self):
-        sysex = (chr(0xF0), chr(0x79), chr(2), chr(1), 'a', 'b', 'c', chr(0xF7))
+        sysex = (chr(0xF0), chr(0x79), chr(2), chr(1), 'a', '\x00', 'b', 
+            '\x00', 'c', '\x00', chr(0xF7))
         self.board.sp.write(sysex)
         while len(self.board.sp):
             self.board.iterate()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.