src/eric7/MicroPython/Devices/MicrobitDevices.py

branch
mpy_network
changeset 9864
f848aacf3447
parent 9834
1fdaebde6316
child 9870
0399d3607829
equal deleted inserted replaced
9863:5f2377b32716 9864:f848aacf3447
51 if serialNumber: 51 if serialNumber:
52 with contextlib.suppress(ValueError): 52 with contextlib.suppress(ValueError):
53 self.__boardId = int(serialNumber[:4], 16) 53 self.__boardId = int(serialNumber[:4], 16)
54 54
55 self.__createMicrobitMenu() 55 self.__createMicrobitMenu()
56
57 self.__bleAddressType = {
58 0: self.tr("Public"),
59 1: self.tr("Random Static"),
60 2: self.tr("Random Private Resolvable"),
61 3: self.tr("Random Private Non-Resolvable"),
62 }
56 63
57 def setConnected(self, connected): 64 def setConnected(self, connected):
58 """ 65 """
59 Public method to set the connection state. 66 Public method to set the connection state.
60 67
716 if self.hasCircuitPython(): 723 if self.hasCircuitPython():
717 return super()._getSetTimeCode() 724 return super()._getSetTimeCode()
718 else: 725 else:
719 return "" 726 return ""
720 727
728 ##################################################################
729 ## Methods below implement Bluetooth related methods
730 ##
731 ## Note: These functions are only available on BBC micro:bit v2
732 ## with CircuitPython firmware loaded. This is handled
733 ## through the 'hasBluetooth()' method.
734 ##
735 ## The Bluetooth related code below is a copy of the one found in
736 ## the CircuitPythonDevices.py module with modifications to cope
737 ## with the limited set of available modules (e.g. no binascii
738 ## or json).
739 ##################################################################
740
741 def hasBluetooth(self):
742 """
743 Public method to check the availability of Bluetooth.
744
745 @return flag indicating the availability of Bluetooth
746 @rtype bool
747 @exception OSError raised to indicate an issue with the device
748 """
749 if not self.hasCircuitPython():
750 return False
751
752 command = """
753 def has_bt():
754 try:
755 import _bleio
756 if hasattr(_bleio, 'adapter'):
757 return True
758 except ImportError:
759 pass
760
761 return False
762
763 print(has_bt())
764 del has_bt
765 """
766 out, err = self._interface.execute(
767 command, mode=self._submitMode, timeout=10000
768 )
769 if err:
770 raise OSError(self._shortError(err))
771 return out.strip() == b"True"
772
773 def getBluetoothStatus(self):
774 """
775 Public method to get Bluetooth status data of the connected board.
776
777 @return list of tuples containing the translated status data label and
778 the associated value
779 @rtype list of tuples of (str, str)
780 @exception OSError raised to indicate an issue with the device
781 """
782 command = """
783 def ble_status():
784 import _bleio
785
786 def address2str(address):
787 return ':'.join('{0:02x}'.format(x) for x in address)
788
789 a = _bleio.adapter
790
791 ble_enabled = a.enabled
792 if not ble_enabled:
793 a.enabled = True
794
795 res = {
796 'active': ble_enabled,
797 'mac': address2str(bytes(reversed(a.address.address_bytes))),
798 'addr_type': a.address.type,
799 'name': a.name,
800 'advertising': a.advertising,
801 'connected': a.connected,
802 }
803
804 if not ble_enabled:
805 a.enabled = False
806
807 print(res)
808
809 ble_status()
810 del ble_status
811 """
812 out, err = self._interface.execute(command, mode=self._submitMode)
813 if err:
814 raise OSError(self._shortError(err))
815
816 status = []
817 bleStatus = ast.literal_eval(out.decode("utf-8"))
818 status.append((self.tr("Active"), self.bool2str(bleStatus["active"])))
819 status.append((self.tr("Name"), bleStatus["name"]))
820 status.append((self.tr("MAC-Address"), bleStatus["mac"]))
821 status.append(
822 (self.tr("Address Type"), self.__bleAddressType[bleStatus["addr_type"]])
823 )
824 status.append((self.tr("Connected"), self.bool2str(bleStatus["connected"])))
825 status.append((self.tr("Advertising"), self.bool2str(bleStatus["advertising"])))
826
827 return status
828
829 def activateBluetoothInterface(self):
830 """
831 Public method to activate the Bluetooth interface.
832
833 @return flag indicating the new state of the Bluetooth interface
834 @rtype bool
835 @exception OSError raised to indicate an issue with the device
836 """
837 command = """
838 def activate_ble():
839 import _bleio
840
841 a = _bleio.adapter
842 if not a.enabled:
843 a.enabled = True
844 print(a.enabled)
845
846 activate_ble()
847 del activate_ble
848 """
849 out, err = self._interface.execute(command, mode=self._submitMode)
850 if err:
851 raise OSError(self._shortError(err))
852
853 return out.strip() == b"True"
854
855 def deactivateBluetoothInterface(self):
856 """
857 Public method to deactivate the Bluetooth interface.
858
859 @return flag indicating the new state of the Bluetooth interface
860 @rtype bool
861 @exception OSError raised to indicate an issue with the device
862 """
863 command = """
864 def deactivate_ble():
865 import _bleio
866
867 a = _bleio.adapter
868 if a.enabled:
869 a.enabled = False
870 print(a.enabled)
871
872 deactivate_ble()
873 del deactivate_ble
874 """
875 out, err = self._interface.execute(command, mode=self._submitMode)
876 if err:
877 raise OSError(self._shortError(err))
878
879 return out.strip() == b"True"
880
881 def getDeviceScan(self, timeout=10):
882 """
883 Public method to perform a Bluetooth device scan.
884
885 @param timeout duration of the device scan in seconds (defaults
886 to 10)
887 @type int (optional)
888 @return tuple containing a dictionary with the scan results and
889 an error string
890 @rtype tuple of (dict, str)
891 """
892 from ..BluetoothDialogs.BluetoothAdvertisement import (
893 ADV_IND,
894 ADV_SCAN_IND,
895 SCAN_RSP,
896 BluetoothAdvertisement,
897 )
898
899 command = """
900 def ble_scan():
901 import _bleio
902 import time
903
904 def address2str(address):
905 return ':'.join('{{0:02x}}'.format(x) for x in address)
906
907 a = _bleio.adapter
908
909 ble_enabled = a.enabled
910 if not ble_enabled:
911 a.enabled = True
912
913 scanResults = a.start_scan(
914 buffer_size=1024, extended=True, timeout={0}, minimum_rssi=-120, active=True
915 )
916 time.sleep({0})
917 a.stop_scan()
918
919 for res in scanResults:
920 print({{
921 'address': address2str(bytes(reversed(res.address.address_bytes))),
922 'advertisement': res.advertisement_bytes,
923 'connectable': res.connectable,
924 'rssi': res.rssi,
925 'scan_response': res.scan_response,
926 }})
927
928 if not ble_enabled:
929 a.enabled = False
930
931 ble_scan()
932 del ble_scan
933 """.format(
934 timeout
935 )
936 out, err = self._interface.execute(
937 command, mode=self._submitMode, timeout=(timeout + 5) * 1000
938 )
939 if err:
940 return {}, err
941
942 scanResults = {}
943 for line in out.decode("utf-8").splitlines():
944 res = ast.literal_eval(line)
945 address = res["address"]
946 if address not in scanResults:
947 scanResults[address] = BluetoothAdvertisement(address)
948 if res["scan_response"]:
949 advType = SCAN_RSP
950 elif res["connectable"]:
951 advType = ADV_IND
952 else:
953 advType = ADV_SCAN_IND
954 scanResults[address].update(advType, res["rssi"], res["advertisement"])
955
956 return scanResults, ""
957
721 958
722 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber): 959 def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):
723 """ 960 """
724 Function to instantiate a MicroPython device object. 961 Function to instantiate a MicroPython device object.
725 962

eric ide

mercurial