652 false) or the complete stat() tuple. 'None' is returned in case the |
652 false) or the complete stat() tuple. 'None' is returned in case the |
653 directory doesn't exist. |
653 directory doesn't exist. |
654 @rtype tuple of (str, tuple) |
654 @rtype tuple of (str, tuple) |
655 @exception OSError raised to indicate an issue with the device |
655 @exception OSError raised to indicate an issue with the device |
656 """ |
656 """ |
657 if self.hasCircuitPython(): |
657 if self.hasCircuitPython() or self.supportsDirectories(): |
658 return super().lls( |
658 return super().lls( |
659 dirname=dirname, fullstat=fullstat, showHidden=showHidden |
659 dirname=dirname, fullstat=fullstat, showHidden=showHidden |
660 ) |
660 ) |
661 else: |
661 else: |
662 # BBC micro:bit with MicroPython does not support directories |
662 # BBC micro:bit with old MicroPython does not support directories |
663 command = """ |
663 command = """ |
664 import os as __os_ |
664 import os as __os_ |
665 |
665 |
666 def is_visible(filename, showHidden): |
666 def is_visible(filename, showHidden): |
667 return showHidden or (filename[0] != '.' and filename[-1] != '~') |
667 return showHidden or (filename[0] != '.' and filename[-1] != '~') |
668 |
668 |
669 def stat(filename): |
669 def stat(filename): |
670 size = __os_.size(filename) |
670 try: |
671 return (0, 0, 0, 0, 0, 0, size, 0, 0, 0) |
671 return __os_.stat(filename) |
|
672 except AttributeError: |
|
673 size = __os_.size(filename) |
|
674 return (0, 0, 0, 0, 0, 0, size, 0, 0, 0) |
672 |
675 |
673 def listdir_stat(showHidden): |
676 def listdir_stat(showHidden): |
674 files = __os_.listdir() |
677 files = __os_.listdir() |
675 return list((f, stat(f)) for f in files if is_visible(f,showHidden)) |
678 return list((f, stat(f)) for f in files if is_visible(f,showHidden)) |
676 |
679 |
699 @rtype str |
702 @rtype str |
700 """ |
703 """ |
701 if self.hasCircuitPython(): |
704 if self.hasCircuitPython(): |
702 return super().pwd() |
705 return super().pwd() |
703 else: |
706 else: |
704 # BBC micro:bit with MicroPython does not support directories |
707 try: |
705 return "" |
708 return super().pwd() |
|
709 except OSError: |
|
710 # BBC micro:bit with old MicroPython does not support directories |
|
711 return "" |
|
712 |
|
713 def rm(self, filename): |
|
714 """ |
|
715 Public method to remove a file from the connected device. |
|
716 |
|
717 @param filename name of the file to be removed |
|
718 @type str |
|
719 """ |
|
720 if filename.startswith("/") and not self.supportsDirectories(): |
|
721 filename = filename[1:] |
|
722 super().rm(filename) |
|
723 |
|
724 def putData(self, deviceFileName, content): |
|
725 """ |
|
726 Public method to write the given data to the connected device. |
|
727 |
|
728 @param deviceFileName name of the file to write to |
|
729 @type str |
|
730 @param content data to write |
|
731 @type bytes |
|
732 @return flag indicating success |
|
733 @rtype bool |
|
734 """ |
|
735 if deviceFileName.startswith("/") and not self.supportsDirectories(): |
|
736 deviceFileName = deviceFileName[1:] |
|
737 return super().putData(deviceFileName, content) |
|
738 |
|
739 def getData(self, deviceFileName): |
|
740 """ |
|
741 Public method to read data from the connected device. |
|
742 |
|
743 @param deviceFileName name of the file to read from |
|
744 @type str |
|
745 @return data read from the device |
|
746 @rtype bytes |
|
747 """ |
|
748 if deviceFileName.startswith("/") and not self.supportsDirectories(): |
|
749 deviceFileName = deviceFileName[1:] |
|
750 return super().getData(deviceFileName) |
706 |
751 |
707 ################################################################## |
752 ################################################################## |
708 ## time related methods below |
753 ## time related methods below |
709 ################################################################## |
754 ################################################################## |
710 |
755 |
968 @return flag indicating that the scanning function is supported |
1013 @return flag indicating that the scanning function is supported |
969 @rtype bool |
1014 @rtype bool |
970 """ |
1015 """ |
971 return True |
1016 return True |
972 |
1017 |
|
1018 def _boardInformationCommands(self): |
|
1019 """ |
|
1020 Protected method defining the list of commands to be execute on the board |
|
1021 for determining information about the board. |
|
1022 |
|
1023 @return list of command strings to be executed |
|
1024 @rtype list of str |
|
1025 """ |
|
1026 # These are a subset of the generic ones. |
|
1027 return [ # needs to be splitted for boards with low memory |
|
1028 """def get_board_info(): |
|
1029 res = {} |
|
1030 |
|
1031 try: |
|
1032 import os |
|
1033 uname = os.uname() |
|
1034 res['sysname'] = uname.sysname |
|
1035 res['nodename'] = uname.nodename |
|
1036 res['release'] = uname.release |
|
1037 res['version'] = uname.version |
|
1038 res['machine'] = uname.machine |
|
1039 except AttributeError: |
|
1040 import sys |
|
1041 res['sysname'] = sys.platform |
|
1042 res['nodename'] = sys.platform |
|
1043 res['release'] = '.'.join(str(v) for v in sys.implementation.version) |
|
1044 res['version'] = sys.version.split(';', 1)[-1].strip() |
|
1045 res['machine'] = sys.implementation._machine |
|
1046 |
|
1047 return res |
|
1048 |
|
1049 print(get_board_info()) |
|
1050 del get_board_info |
|
1051 """, |
|
1052 """def get_board_info(): |
|
1053 res = {} |
|
1054 |
|
1055 import sys |
|
1056 res['py_platform'] = sys.platform |
|
1057 res['py_version'] = sys.version |
|
1058 |
|
1059 try: |
|
1060 res['mpy_name'] = sys.implementation.name |
|
1061 except AttributeError: |
|
1062 res['mpy_name'] = 'unknown' |
|
1063 try: |
|
1064 res['mpy_version'] = '.'.join((str(i) for i in sys.implementation.version)) |
|
1065 except AttributeError: |
|
1066 res['mpy_version'] = 'unknown' |
|
1067 try: |
|
1068 import pimoroni |
|
1069 res['mpy_variant'] = 'Pimoroni Pico' |
|
1070 try: |
|
1071 import version |
|
1072 res['mpy_variant_info'] = version.BUILD |
|
1073 res['mpy_variant_version'] = version.BUILD.split('-')[2][1:] |
|
1074 except ImportError: |
|
1075 res['mpy_variant_info'] = '' |
|
1076 res['mpy_variant_version'] = '' |
|
1077 except ImportError: |
|
1078 res['mpy_variant'] = '' |
|
1079 res['mpy_variant_info'] = '' |
|
1080 res['mpy_variant_version'] = '' |
|
1081 |
|
1082 return res |
|
1083 |
|
1084 print(get_board_info()) |
|
1085 del get_board_info |
|
1086 """, |
|
1087 """def get_board_info(): |
|
1088 res = {} |
|
1089 |
|
1090 try: |
|
1091 import ulab |
|
1092 res['ulab'] = ulab.__version__ |
|
1093 except ImportError: |
|
1094 res['ulab'] = None |
|
1095 |
|
1096 return res |
|
1097 |
|
1098 print(get_board_info()) |
|
1099 del get_board_info |
|
1100 """, |
|
1101 # micro:bit specific variants due to missing float support |
|
1102 """def get_board_info(): |
|
1103 res = {} |
|
1104 |
|
1105 import gc |
|
1106 gc.enable() |
|
1107 gc.collect() |
|
1108 mem_alloc = gc.mem_alloc() |
|
1109 mem_free = gc.mem_free() |
|
1110 mem_total = mem_alloc + mem_free |
|
1111 res['mem_total'] = mem_total |
|
1112 res['mem_used'] = mem_alloc |
|
1113 res['mem_free'] = mem_free |
|
1114 del gc, mem_alloc, mem_free, mem_total |
|
1115 |
|
1116 return res |
|
1117 |
|
1118 print(get_board_info()) |
|
1119 del get_board_info |
|
1120 """, |
|
1121 """def get_board_info(): |
|
1122 res = {} |
|
1123 |
|
1124 try: |
|
1125 import os |
|
1126 stat_ = os.statvfs('/flash') |
|
1127 res['flash_info_available'] = True |
|
1128 res['flash_total'] = stat_[2] * stat_[0] |
|
1129 res['flash_free'] = stat_[3] * stat_[0] |
|
1130 except (AttributeError, OSError): |
|
1131 res['flash_info_available'] = False |
|
1132 |
|
1133 return res |
|
1134 |
|
1135 print(get_board_info()) |
|
1136 del get_board_info |
|
1137 """, |
|
1138 """def get_board_info(): |
|
1139 res = {} |
|
1140 |
|
1141 import machine as mc |
|
1142 import microbit as mb |
|
1143 try: |
|
1144 if isinstance(mc.freq(), tuple): |
|
1145 res['mc_frequency'] = mc.freq()[0] |
|
1146 else: |
|
1147 res['mc_frequency'] = mc.freq() |
|
1148 except NotImplementedError: |
|
1149 res['mc_frequency'] = None |
|
1150 try: |
|
1151 res['mc_temp_c'] = mc.Temp().read() |
|
1152 except AttributeError: |
|
1153 try: |
|
1154 res['mc_temp_c'] = mb.temperature() * 100 |
|
1155 except AttributeError: |
|
1156 res['mc_temp_c'] = None |
|
1157 res['mc_id'] = mc.unique_id() |
|
1158 if 'mc_id' in res: |
|
1159 res['mc_id'] = ':'.join('{0:02X}'.format(x) for x in res['mc_id']) |
|
1160 else: |
|
1161 res['mc_id'] = None |
|
1162 |
|
1163 return res |
|
1164 |
|
1165 print(get_board_info()) |
|
1166 del get_board_info |
|
1167 """, |
|
1168 ] |
973 |
1169 |
974 def getBoardInformation(self): |
1170 def getBoardInformation(self): |
975 """ |
1171 """ |
976 Public method to get some information data of the connected board. |
1172 Public method to get some information data of the connected board. |
977 |
1173 |
978 @return dictionary containing the determined data |
1174 @return dictionary containing the determined data |
979 @rtype dict |
1175 @rtype dict |
980 """ |
1176 """ |
981 res = super().getBoardInformation() |
1177 res = super().getBoardInformation() |
|
1178 |
|
1179 # post-process the results to determine the right float entries |
|
1180 |
|
1181 # 1. memory |
|
1182 res["mem_total_kb"] = res["mem_total"] / 1024.0 |
|
1183 res["mem_used_kb"] = res["mem_used"] / 1024.0 |
|
1184 res["mem_used_pc"] = res["mem_used"] / res["mem_total"] * 100.0 |
|
1185 res["mem_free_kb"] = res["mem_free"] / 1024.0 |
|
1186 res["mem_free_pc"] = res["mem_free"] / res["mem_total"] * 100.0 |
|
1187 |
|
1188 # 2. flash |
|
1189 if res["flash_info_available"]: |
|
1190 res["flash_total_kb"] = res["flash_total"] / 1024.0 |
|
1191 res["flash_free_kb"] = res["flash_free"] / 1024.0 |
|
1192 res["flash_used_kb"] = res["flash_total_kb"] - res["flash_free_kb"] |
|
1193 res["flash_free_pc"] = res["flash_free_kb"] / res["flash_total_kb"] * 100.0 |
|
1194 res["flash_used_pc"] = res["flash_used_kb"] / res["flash_total_kb"] * 100.0 |
|
1195 |
|
1196 # 3. machine |
|
1197 res["mc_frequency_mhz"] = ( |
|
1198 res["mc_frequency"] / 1000000.0 if res["mc_frequency"] is not None else None |
|
1199 ) |
982 with contextlib.suppress(KeyError): |
1200 with contextlib.suppress(KeyError): |
983 if res["mc_temp_c"] is not None: |
1201 if res["mc_temp_c"] is not None: |
984 res["mc_temp_c"] = res["mc_temp_c"] / 100 # due to integer support only |
1202 res["mc_temp_c"] = res["mc_temp_c"] / 100 # due to integer support only |
985 |
1203 |
986 return res |
1204 return res |
|
1205 |
|
1206 def isMicrobit(self): |
|
1207 """ |
|
1208 Public method to check, if the device is a BBC micro:bit or Calliope mini. |
|
1209 |
|
1210 @return flag indicating a micro:bit device |
|
1211 @rtype bool |
|
1212 """ |
|
1213 if ( |
|
1214 ("micro:bit" in self.deviceName() or "Calliope" in self.deviceName()) |
|
1215 and not self.hasCircuitPython() |
|
1216 and not self.supportsDirectories() |
|
1217 ): |
|
1218 return True |
|
1219 |
|
1220 return False |
987 |
1221 |
988 |
1222 |
989 def createDevice(microPythonWidget, deviceType, _vid, _pid, _boardName, serialNumber): |
1223 def createDevice(microPythonWidget, deviceType, _vid, _pid, _boardName, serialNumber): |
990 """ |
1224 """ |
991 Function to instantiate a MicroPython device object. |
1225 Function to instantiate a MicroPython device object. |