Mbed LS
lstools_base.py
Go to the documentation of this file.
1 """
2 mbed SDK
3 Copyright (c) 2011-2015 ARM Limited
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 """
17 
18 import re
19 import os
20 import sys
21 import functools
22 from os.path import expanduser
23 from io import open
24 import json
25 from os import listdir
26 from os.path import isfile, join, exists, isdir
27 import logging
28 from abc import ABCMeta, abstractmethod
29 
30 from .platform_database import PlatformDatabase, LOCAL_PLATFORM_DATABASE, \
31  LOCAL_MOCKS_DATABASE
32 mbedls_root_logger = logging.getLogger("mbedls")
33 mbedls_root_logger.setLevel(logging.WARNING)
34 
35 logger = logging.getLogger("mbedls.lstools_base")
36 logger.addHandler(logging.NullHandler())
37 
38 def deprecated(reason):
39  """Deprecate a function/method with a decorator"""
40  def actual_decorator(func):
41  @functools.wraps(func)
42  def new_func(*args, **kwargs):
43  logger.warning("Call to deprecated function %s. %s",
44  func.__name__, reason)
45  return func(*args, **kwargs)
46  return new_func
47  return actual_decorator
48 
50  BeforeFilter = 1
51  AfterFilter = 2
52  Never = 3
53 
55  """ Base class for mbed-lstools, defines mbed-ls tools interface for
56  mbed-enabled devices detection for various hosts
57  """
58 
59  __metaclass__ = ABCMeta
60 
61  # Which OSs are supported by this module
62  # Note: more than one OS can be supported by mbed-lstools_* module
63  os_supported = []
64 
65  # Directory where we will store global (OS user specific mocking)
66  HOME_DIR = expanduser("~")
67  MOCK_FILE_NAME = '.mbedls-mock'
68  RETARGET_FILE_NAME = 'mbedls.json'
69  DETAILS_TXT_NAME = 'DETAILS.TXT'
70  MBED_HTM_NAME = 'mbed.htm'
71 
72  VENDOR_ID_DEVICE_TYPE_MAP = {
73  '0483': 'stlink',
74  '0d28': 'daplink',
75  '1366': 'jlink',
76  '03eb': 'atmel'
77  }
78 
79  def __init__(self, list_unmounted=False, **kwargs):
80  """ ctor
81  """
82  self.retarget_data = {} # Used to retarget mbed-enabled platform properties
83 
84  platform_dbs = []
85  if isfile(self.MOCK_FILE_NAME) or ("force_mock" in kwargs and kwargs['force_mock']):
86  platform_dbs.append(self.MOCK_FILE_NAME)
87  elif isfile(LOCAL_MOCKS_DATABASE):
88  platform_dbs.append(LOCAL_MOCKS_DATABASE)
89  platform_dbs.append(LOCAL_PLATFORM_DATABASE)
90  self.plat_db = PlatformDatabase(platform_dbs,
91  primary_database=platform_dbs[0])
92  self.list_unmounted = list_unmounted
93 
94  if 'skip_retarget' not in kwargs or not kwargs['skip_retarget']:
95  self.retarget()
96 
97  @abstractmethod
98  def find_candidates(self):
99  """Find all candidate devices connected to this computer
100 
101  Note: Should not open any files
102 
103  @return A dict with the keys 'mount_point', 'serial_port' and 'target_id_usb_id'
104  """
105  raise NotImplemented
106 
107  @deprecated("Functionality has been moved into 'list_mbeds'. "
108  "Please use list_mbeds with 'unique_names=True' and "
109  "'read_details_txt=True'")
110  def list_mbeds_ext(self):
111  """! Function adds extra information for each mbed device
112  @return Returns list of mbed devices plus extended data like 'platform_name_unique'
113  @details Get information about mbeds with extended parameters/info included
114  """
115 
116  return self.list_mbeds(unique_names=True, read_details_txt=True)
117 
119  self, fs_interaction=FSInteraction.BeforeFilter,
120  filter_function=None, unique_names=False,
121  read_details_txt=False):
122  """ List details of connected devices
123  @return Returns list of structures with detailed info about each mbed
124  @param fs_interaction A member of the FSInteraction class that picks the
125  trade of between quality of service and speed
126  @param filter_function Function that is passed each mbed candidate,
127  should return True if it should be included in the result
128  Ex. mbeds = list_mbeds(filter_function=lambda m: m['platform_name'] == 'K64F')
129  @param unique_names A boolean controlling the presence of the
130  'platform_unique_name' member of the output dict
131  @param read_details_txt A boolean controlling the presense of the
132  output dict attributes read from other files present on the 'mount_point'
133  @details Function returns list of dictionaries with mbed attributes 'mount_point', TargetID name etc.
134  Function returns mbed list with platform names if possible
135  """
136  platform_count = {}
137  candidates = list(self.find_candidates())
138  logger.debug("Candidates for display %r", candidates)
139  result = []
140  for device in candidates:
141  device['device_type'] = self._detect_device_type(device)
142  if ((not device['mount_point'] or
143  not self.mount_point_ready(device['mount_point'])) and
144  not self.list_unmounted):
145  if (device['target_id_usb_id'] and device['serial_port']):
146  logger.warning(
147  "MBED with target id '%s' is connected, but not mounted. "
148  "Use the '-u' flag to include it in the list.",
149  device['target_id_usb_id'])
150  else:
151  platform_data = self.plat_db.get(device['target_id_usb_id'][0:4],
152  device_type=device['device_type'] or 'daplink', verbose_data=True)
153  device.update(platform_data or {"platform_name": None})
154  maybe_device = {
155  FSInteraction.BeforeFilter: self._fs_before_id_check,
156  FSInteraction.AfterFilter: self._fs_after_id_check,
157  FSInteraction.Never: self._fs_never
158  }[fs_interaction](device, filter_function, read_details_txt)
159  if maybe_device and (maybe_device['mount_point'] or self.list_unmounted):
160  if unique_names:
161  name = device['platform_name']
162  platform_count.setdefault(name, -1)
163  platform_count[name] += 1
164  device['platform_name_unique'] = (
165  "%s[%d]" % (name, platform_count[name]))
166  try:
167  device.update(self.retarget_data[device['target_id']])
168  logger.debug("retargeting %s with %r",
169  device['target_id'],
170  self.retarget_data[device['target_id']])
171  except KeyError:
172  pass
173 
174  # This is done for API compatibility, would prefer for this to just be None
175  device['device_type'] = device['device_type'] if device['device_type'] else 'unknown'
176  result.append(maybe_device)
177 
178  return result
179 
180  def _fs_never(self, device, filter_function, read_details_txt):
181  """Filter device without touching the file system of the device"""
182  device['target_id'] = device['target_id_usb_id']
183  device['target_id_mbed_htm'] = None
184  if not filter_function or filter_function(device):
185  return device
186  else:
187  return None
188 
189  def _fs_before_id_check(self, device, filter_function, read_details_txt):
190  """Filter device after touching the file system of the device.
191  Said another way: Touch the file system before filtering
192  """
193 
194  device['target_id'] = device['target_id_usb_id']
195  self._update_device_from_fs(device, read_details_txt)
196  if not filter_function or filter_function(device):
197  return device
198  else:
199  return None
200 
201  def _fs_after_id_check(self, device, filter_function, read_details_txt):
202  """Filter device before touching the file system of the device.
203  Said another way: Touch the file system after filtering
204  """
205  device['target_id'] = device['target_id_usb_id']
206  device['target_id_mbed_htm'] = None
207  if not filter_function or filter_function(device):
208  self._update_device_from_fs(device, read_details_txt)
209  return device
210  else:
211  return None
212 
213  def _update_device_from_fs(self, device, read_details_txt):
214  """ Updates the device information based on files from its 'mount_point'
215  @param device Dictionary containing device information
216  @param read_details_txt A boolean controlling the presense of the
217  output dict attributes read from other files present on the 'mount_point'
218  """
219  if not device.get('mount_point', None):
220  return
221 
222  try:
223  directory_entries = os.listdir(device['mount_point'])
224  device['directory_entries'] = directory_entries
225  device['target_id'] = device['target_id_usb_id']
226 
227  # Always try to update using daplink compatible boards processself.
228  # This is done for backwards compatibility.
229  self._update_device_details_daplink_compatible(device, read_details_txt)
230 
231  if device.get('device_type') == 'jlink':
232  self._update_device_details_jlink(device, read_details_txt)
233 
234  if device.get('device_type') == 'atmel':
235  self._update_device_details_atmel(device, read_details_txt)
236 
237  except (OSError, IOError) as e:
238  logger.warning(
239  'Marking device with mount point "%s" as unmounted due to the '
240  'following error: %s', device['mount_point'], e)
241  device['mount_point'] = None
242 
243 
244  def _detect_device_type(self, device):
245  """ Returns a string of the device type
246  @param device Dictionary containing device information
247  @return Device type located in VENDOR_ID_DEVICE_TYPE_MAP or None if unknown
248  """
249 
250  return self.VENDOR_ID_DEVICE_TYPE_MAP.get(device.get('vendor_id'))
251 
252 
253  def _update_device_details_daplink_compatible(self, device, read_details_txt):
254  """ Updates the daplink-specific device information based on files from its 'mount_point'
255  @param device Dictionary containing device information
256  @param read_details_txt A boolean controlling the presense of the
257  output dict attributes read from other files present on the 'mount_point'
258  """
259  lowercase_directory_entries = [e.lower() for e in device['directory_entries']]
260  if self.MBED_HTM_NAME.lower() in lowercase_directory_entries:
261  self._update_device_from_htm(device)
262  elif not read_details_txt:
263  logger.debug('Since mbed.htm is not present, attempting to use '
264  'details.txt for the target id')
265  read_details_txt = True
266 
267  if read_details_txt and self.DETAILS_TXT_NAME.lower() in lowercase_directory_entries:
268  details_txt = self._details_txt(device['mount_point']) or {}
269  device.update({"daplink_%s" % f.lower().replace(' ', '_'): v
270  for f, v in details_txt.items()})
271 
272  # If details.txt contains the target id, this is the most trusted source
273  if device.get('daplink_unique_id', None):
274  device['target_id'] = device['daplink_unique_id']
275 
276  if device['target_id']:
277  identifier = device['target_id'][0:4]
278  platform_data = self.plat_db.get(identifier,
279  device_type='daplink',
280  verbose_data=True)
281  if not platform_data:
282  logger.warning('daplink entry: "%s" not found in platform database', identifier)
283  else:
284  device.update(platform_data)
285  else:
286  device['platform_name'] = None
287 
288  def _update_device_details_jlink(self, device, _):
289  """ Updates the jlink-specific device information based on files from its 'mount_point'
290  @param device Dictionary containing device information
291  """
292  lower_case_map = {e.lower(): e for e in device['directory_entries']}
293 
294  if 'board.html' in lower_case_map:
295  board_file_key = 'board.html'
296  elif 'user guide.html' in lower_case_map:
297  board_file_key = 'user guide.html'
298  else:
299  logger.warning('No valid file found to update JLink device details')
300  return
301 
302  board_file_path = os.path.join(device['mount_point'], lower_case_map[board_file_key])
303  with open(board_file_path, 'r') as board_file:
304  board_file_lines = board_file.readlines()
305 
306  for line in board_file_lines:
307  m = re.search(r'url=([\w\d\:\-/\\\?\.=-_]+)', line)
308  if m:
309  device['url'] = m.group(1).strip()
310  identifier = device['url'].split('/')[-1]
311  platform_data = self.plat_db.get(identifier,
312  device_type='jlink',
313  verbose_data=True)
314  if not platform_data:
315  logger.warning('jlink entry: "%s", not found in platform database', identifier)
316  else:
317  device.update(platform_data)
318  break
319 
320  def _update_device_from_htm(self, device):
321  """Set the 'target_id', 'target_id_mbed_htm', 'platform_name' and
322  'daplink_*' attributes by reading from mbed.htm on the device
323  """
324  htm_target_id, daplink_info = self._read_htm_ids(device['mount_point'])
325  if daplink_info:
326  device.update({"daplink_%s" % f.lower().replace(' ', '_'): v
327  for f, v in daplink_info.items()})
328  if htm_target_id:
329  logger.debug("Found htm target id, %s, for usb target id %s",
330  htm_target_id, device['target_id_usb_id'])
331  device['target_id'] = htm_target_id
332  else:
333  logger.debug("Could not read htm on from usb id %s. "
334  "Falling back to usb id",
335  device['target_id_usb_id'])
336  device['target_id'] = device['target_id_usb_id']
337  device['target_id_mbed_htm'] = htm_target_id
338 
339  def _update_device_details_atmel(self, device, _):
340  """ Updates the Atmel device information based on files from its 'mount_point'
341  @param device Dictionary containing device information
342  @param read_details_txt A boolean controlling the presense of the
343  output dict attributes read from other files present on the 'mount_point'
344  """
345 
346  # Atmel uses a system similar to DAPLink, but there's no details.txt with a target ID
347  # to identify device we can use the serial, which is ATMLXXXXYYYYYYY
348  # where XXXX is the board identifier.
349  # This can be verified by looking at readme.htm, which also uses the board ID to redirect to platform page
350 
351  device['target_id'] = device['target_id_usb_id'][4:8]
352  platform_data = self.plat_db.get(device['target_id'],
353  device_type='atmel',
354  verbose_data=True)
355 
356  device.update(platform_data or {"platform_name": None})
357 
358  def mock_manufacture_id(self, mid, platform_name, oper='+'):
359  """! Replace (or add if manufacture id doesn't exist) entry in self.manufacture_ids
360  @param oper '+' add new mock / override existing entry
361  '-' remove mid from mocking entry
362  @return Mocked structure (json format)
363  """
364  if oper is '+':
365  self.plat_db.add(mid, platform_name, permanent=True)
366  elif oper is '-':
367  self.plat_db.remove(mid, permanent=True)
368  else:
369  raise ValueError("oper can only be [+-]")
370 
371  @deprecated("List formatting methods are deprecated for a simpler API. "
372  "Please use 'list_mbeds' instead.")
374  """! Creates list of all available mappings for target_id -> Platform
375  @return String with table formatted output
376  """
377  from prettytable import PrettyTable, HEADER
378 
379  columns = ['target_id_prefix', 'platform_name']
380  pt = PrettyTable(columns, junction_char="|", hrules=HEADER)
381  for col in columns:
382  pt.align[col] = 'l'
383 
384  for target_id_prefix, platform_name in sorted(self.plat_db.items()):
385  pt.add_row([target_id_prefix, platform_name])
386 
387  return pt.get_string()
388 
389  def retarget_read(self):
390  """! Load retarget data from local file
391  @return Curent retarget configuration (dictionary)
392  """
393  if os.path.isfile(self.RETARGET_FILE_NAME):
394  logger.debug("reading retarget file %s", self.RETARGET_FILE_NAME)
395  try:
396  with open(self.RETARGET_FILE_NAME, "r", encoding="utf-8") as f:
397  return json.load(f)
398  except IOError as e:
399  logger.exception(e)
400  except ValueError as e:
401  logger.exception(e)
402  return {}
403 
404  def retarget(self):
405  """! Enable retargeting
406  @details Read data from local retarget configuration file
407  @return Retarget data structure read from configuration file
408  """
409  self.retarget_data = self.retarget_read()
410  return self.retarget_data
411 
412  def get_dummy_platform(self, platform_name):
413  """! Returns simple dummy platform """
414  if not hasattr(self, "dummy_counter"):
415  self.dummy_counter = {} # platform<str>: counter<int>
416 
417  if platform_name not in self.dummy_counter:
418  self.dummy_counter[platform_name] = 0
419 
420  platform = {
421  "platform_name": platform_name,
422  "platform_name_unique": "%s[%d]"% (platform_name, self.dummy_counter[platform_name]),
423  "mount_point": "DUMMY",
424  "serial_port": "DUMMY",
425  "target_id": "DUMMY",
426  "target_id_mbed_htm": "DUMMY",
427  "target_id_usb_id": "DUMMY",
428  "daplink_version": "DUMMY"
429  }
430  self.dummy_counter[platform_name] += 1
431  return platform
432 
433  def get_supported_platforms(self, device_type=None):
434  """! Return a dictionary of supported target ids and the corresponding platform name
435  @param device_type Filter which device entries are returned from the platform database
436  @return Dictionary of { 'target_id': 'platform_name', ... }
437  """
438  kwargs = {}
439  if device_type is not None:
440  kwargs['device_type'] = device_type
441 
442  items = self.plat_db.items(**kwargs)
443  return {i[0]: i[1] for i in items}
444 
445  @deprecated("List formatting methods are deprecated to simplify the API. "
446  "Please use 'list_mbeds' instead.")
447  def list_platforms(self):
448  """! Useful if you just want to know which platforms are currently available on the system
449  @return List of (unique values) available platforms
450  """
451  result = []
452  mbeds = self.list_mbeds()
453  for i, val in enumerate(mbeds):
454  platform_name = str(val['platform_name'])
455  if platform_name not in result:
456  result.append(platform_name)
457  return result
458 
459  @deprecated("List formatting methods are deprecated to simplify the API. "
460  "Please use 'list_mbeds' instead.")
462  """! Useful if you just want to know how many platforms of each type are currently available on the system
463  @return Dict of platform: platform_count
464  """
465  result = {}
466  mbeds = self.list_mbeds()
467  for i, val in enumerate(mbeds):
468  platform_name = str(val['platform_name'])
469  if platform_name not in result:
470  result[platform_name] = 1
471  else:
472  result[platform_name] += 1
473  return result
474 
475  @deprecated("List formatting methods are deprecated to simplify the API. "
476  "Please use 'list_mbeds' instead.")
478  """! Get information about mbeds with extended parameters/info included
479  @return Returns dictionary where keys are TargetIDs and values are mbed structures
480  @details Ordered by target id (key: target_id).
481  """
482  result = {}
483  mbed_list = self.list_mbeds_ext()
484  for mbed in mbed_list:
485  target_id = mbed['target_id']
486  result[target_id] = mbed
487  return result
488 
489  def __str__(self):
490  """! Object to string casting
491 
492  @return Stringified class object should be prettytable formated string
493  """
494  return self.get_string()
495 
496  @deprecated("List formatting methods are deprecated to simplify the API. "
497  "Please use 'list_mbeds' instead.")
498  def get_string(self, border=False, header=True, padding_width=1, sortby='platform_name'):
499  """! Printing with some sql table like decorators
500  @param border Table border visibility
501  @param header Table header visibility
502  @param padding_width Table padding
503  @param sortby Column used to sort results
504  @return Returns string which can be printed on console
505  """
506  from prettytable import PrettyTable, HEADER
507  result = ''
508  mbeds = self.list_mbeds(unique_names=True, read_details_txt=True)
509  if mbeds:
510  """ ['platform_name', 'mount_point', 'serial_port', 'target_id'] - columns generated from USB auto-detection
511  ['platform_name_unique', ...] - columns generated outside detection subsystem (OS dependent detection)
512  """
513  columns = ['platform_name', 'platform_name_unique', 'mount_point', 'serial_port', 'target_id', 'daplink_version']
514  pt = PrettyTable(columns, junction_char="|", hrules=HEADER)
515  for col in columns:
516  pt.align[col] = 'l'
517 
518  for mbed in mbeds:
519  row = []
520  for col in columns:
521  row.append(mbed[col] if col in mbed and mbed[col] else 'unknown')
522  pt.add_row(row)
523  result = pt.get_string(border=border, header=header, padding_width=padding_width, sortby=sortby)
524  return result
525 
526  # Private functions supporting API
527 
528  @deprecated("This method will be removed from the public API. "
529  "Please use 'list_mbeds' instead")
530  def get_json_data_from_file(self, json_spec_filename, verbose=False):
531  """! Loads from file JSON formatted string to data structure
532  @return None if JSON can be loaded
533  """
534  try:
535  with open(json_spec_filename) as data_file:
536  try:
537  return json.load(data_file)
538  except ValueError as json_error_msg:
539  logger.error("Parsing file(%s): %s", json_spec_filename, json_error_msg)
540  return None
541  except IOError as fileopen_error_msg:
542  logger.warning(fileopen_error_msg)
543  return None
544 
545  @deprecated("This method will be removed from the public API. "
546  "Please use 'list_mbeds' instead")
547  def get_htm_target_id(self, mount_point):
548  target_id, _ = self._read_htm_ids(mount_point)
549  return target_id
550 
551  @deprecated("This method will be removed from the public API. "
552  "Please use 'list_mbeds' instead")
553  def get_mbed_htm(self, mount_point):
554  _, build_info = self._read_htm_ids(mount_point)
555  return build_info
556 
557  def _read_htm_ids(self, mount_point):
558  """! Function scans mbed.htm to get information about TargetID.
559  @param mount_point mbed mount point (disk / drive letter)
560  @return Function returns targetID, in case of failure returns None.
561  @details Note: This function should be improved to scan variety of boards' mbed.htm files
562  """
563  result = {}
564  target_id = None
565  for line in self._htm_lines(mount_point):
566  target_id = target_id or self._target_id_from_htm(line)
567  ver_bld = self._mbed_htm_comment_section_ver_build(line)
568  if ver_bld:
569  result['version'], result['build'] = ver_bld
570 
571  m = re.search(r'url=([\w\d\:/\\\?\.=-_]+)', line)
572  if m:
573  result['url'] = m.group(1).strip()
574  return target_id, result
575 
576  @deprecated("This method will be removed from the public API. "
577  "Please use 'list_mbeds' instead")
579  return self._mbed_htm_comment_section_ver_build(line)
580 
581  def _mbed_htm_comment_section_ver_build(self, line):
582  """! Check for Version and Build date of interface chip firmware im mbed.htm file
583  @return (version, build) tuple if successful, None if no info found
584  """
585  # <!-- Version: 0200 Build: Mar 26 2014 13:22:20 -->
586  m = re.search(r'^<!-- Version: (\d+) Build: ([\d\w: ]+) -->', line)
587  if m:
588  version_str, build_str = m.groups()
589  return (version_str.strip(), build_str.strip())
590 
591  # <!-- Version: 0219 Build: Feb 2 2016 15:20:54 Git Commit SHA: 0853ba0cdeae2436c52efcba0ba76a6434c200ff Git local mods:No-->
592  m = re.search(r'^<!-- Version: (\d+) Build: ([\d\w: ]+) Git Commit SHA', line)
593  if m:
594  version_str, build_str = m.groups()
595  return (version_str.strip(), build_str.strip())
596 
597  # <!-- Version: 0.14.3. build 471 -->
598  m = re.search(r'^<!-- Version: ([\d+\.]+)\. build (\d+) -->', line)
599  if m:
600  version_str, build_str = m.groups()
601  return (version_str.strip(), build_str.strip())
602  return None
603 
604  @deprecated("This method will be removed from the public API. "
605  "Please use 'list_mbeds' instead")
606  def get_mbed_htm_lines(self, mount_point):
607  return self._htm_lines(mount_point)
608 
609  def _htm_lines(self, mount_point):
610  if mount_point:
611  mbed_htm_path = join(mount_point, self.MBED_HTM_NAME)
612  with open(mbed_htm_path, 'r') as f:
613  return f.readlines()
614 
615  @deprecated("This method will be removed from the public API. "
616  "Please use 'list_mbeds' instead")
617  def get_details_txt(self, mount_point):
618  return self._details_txt(mount_point)
619 
620  def _details_txt(self, mount_point):
621  """! Load DETAILS.TXT to dictionary:
622  DETAILS.TXT example:
623  Version: 0226
624  Build: Aug 24 2015 17:06:30
625  Git Commit SHA: 27a236b9fe39c674a703c5c89655fbd26b8e27e1
626  Git Local mods: Yes
627 
628  or:
629 
630  # DAPLink Firmware - see https://mbed.com/daplink
631  Unique ID: 0240000029164e45002f0012706e0006f301000097969900
632  HIF ID: 97969900
633  Auto Reset: 0
634  Automation allowed: 0
635  Daplink Mode: Interface
636  Interface Version: 0240
637  Git SHA: c765cbb590f57598756683254ca38b211693ae5e
638  Local Mods: 0
639  USB Interfaces: MSD, CDC, HID
640  Interface CRC: 0x26764ebf
641  """
642 
643  if mount_point:
644  path_to_details_txt = os.path.join(mount_point, self.DETAILS_TXT_NAME)
645  with open(path_to_details_txt, 'r') as f:
646  return self._parse_details(f.readlines())
647  return None
648 
649  @deprecated("This method will be removed from the public API. "
650  "Please use 'list_mbeds' instead")
651  def parse_details_txt(self, lines):
652  return self._parse_details(lines)
653 
654  def _parse_details(self, lines):
655  result = {}
656  for line in lines:
657  if not line.startswith('#'):
658  key, _, value = line.partition(':')
659  if value:
660  result[key] = value.strip()
661  if 'Interface Version' in result:
662  result['Version'] = result['Interface Version']
663  return result
664 
665  @deprecated("This method will be removed from the public API. "
666  "Please use 'list_mbeds' instead")
668  return self._target_id_from_htm(line)
669 
670  def _target_id_from_htm(self, line):
671  """! Extract Target id from htm line.
672  @return Target id or None
673  """
674  # Detecting modern mbed.htm file format
675  m = re.search('\?code=([a-fA-F0-9]+)', line)
676  if m:
677  result = m.groups()[0]
678  logger.debug("Found target id %s in htm line %s", result, line)
679  return result
680  # Last resort, we can try to see if old mbed.htm format is there
681  m = re.search('\?auth=([a-fA-F0-9]+)', line)
682  if m:
683  result = m.groups()[0]
684  logger.debug("Found target id %s in htm line %s", result, line)
685  return result
686 
687  return None
688 
689  def mount_point_ready(self, path):
690  """! Check if a mount point is ready for file operations
691  """
692  return exists(path) and isdir(path)
693 
694  @staticmethod
695  @deprecated("This method will be removed from the public API. "
696  "Please use 'list_mbeds' instead")
697  def run_cli_process(cmd, shell=True):
698  return MbedLsToolsBase._run_cli_process(cmd, shell)
699 
700  @staticmethod
701  def _run_cli_process(cmd, shell=True):
702  """! Runs command as a process and return stdout, stderr and ret code
703  @param cmd Command to execute
704  @return Tuple of (stdout, stderr, returncode)
705  """
706  from subprocess import Popen, PIPE
707 
708  p = Popen(cmd, shell=shell, stdout=PIPE, stderr=PIPE)
709  _stdout, _stderr = p.communicate()
710  return _stdout, _stderr, p.returncode
mbed_lstools.lstools_base.MbedLsToolsBase.list_mbeds_by_targetid
def list_mbeds_by_targetid(self)
Get information about mbeds with extended parameters/info included.
Definition: lstools_base.py:477
mbed_lstools.lstools_base.MbedLsToolsBase.retarget_data
retarget_data
Definition: lstools_base.py:82
mbed_lstools.lstools_base.MbedLsToolsBase._read_htm_ids
def _read_htm_ids(self, mount_point)
Function scans mbed.htm to get information about TargetID.
Definition: lstools_base.py:557
mbed_lstools.lstools_base.MbedLsToolsBase.get_mbed_htm_lines
def get_mbed_htm_lines(self, mount_point)
Definition: lstools_base.py:606
mbed_lstools.lstools_base.MbedLsToolsBase._update_device_details_atmel
def _update_device_details_atmel(self, device, _)
Definition: lstools_base.py:339
mbed_lstools.lstools_base.MbedLsToolsBase._fs_never
def _fs_never(self, device, filter_function, read_details_txt)
Definition: lstools_base.py:180
mbed_lstools.lstools_base.MbedLsToolsBase.MBED_HTM_NAME
string MBED_HTM_NAME
Definition: lstools_base.py:70
mbed_lstools.lstools_base.MbedLsToolsBase._update_device_from_fs
def _update_device_from_fs(self, device, read_details_txt)
Definition: lstools_base.py:213
mbed_lstools.lstools_base.MbedLsToolsBase._htm_lines
def _htm_lines(self, mount_point)
Definition: lstools_base.py:609
mbed_lstools.lstools_base.MbedLsToolsBase.list_platforms_ext
def list_platforms_ext(self)
Useful if you just want to know how many platforms of each type are currently available on the system...
Definition: lstools_base.py:461
mbed_lstools.lstools_base.MbedLsToolsBase.get_string
def get_string(self, border=False, header=True, padding_width=1, sortby='platform_name')
Printing with some sql table like decorators.
Definition: lstools_base.py:498
mbed_lstools.lstools_base.MbedLsToolsBase.get_mbed_htm
def get_mbed_htm(self, mount_point)
Definition: lstools_base.py:553
mbed_lstools.lstools_base.MbedLsToolsBase.retarget_read
def retarget_read(self)
Load retarget data from local file.
Definition: lstools_base.py:389
mbed_lstools.lstools_base.MbedLsToolsBase._detect_device_type
def _detect_device_type(self, device)
Definition: lstools_base.py:244
mbed_lstools.lstools_base.MbedLsToolsBase.get_json_data_from_file
def get_json_data_from_file(self, json_spec_filename, verbose=False)
Loads from file JSON formatted string to data structure.
Definition: lstools_base.py:530
mbed_lstools.lstools_base.MbedLsToolsBase._parse_details
def _parse_details(self, lines)
Definition: lstools_base.py:654
mbed_lstools.lstools_base.MbedLsToolsBase._update_device_details_jlink
def _update_device_details_jlink(self, device, _)
Definition: lstools_base.py:288
mbed_lstools.lstools_base.MbedLsToolsBase._mbed_htm_comment_section_ver_build
def _mbed_htm_comment_section_ver_build(self, line)
Check for Version and Build date of interface chip firmware im mbed.htm file.
Definition: lstools_base.py:581
mbed_lstools.lstools_base.MbedLsToolsBase._update_device_details_daplink_compatible
def _update_device_details_daplink_compatible(self, device, read_details_txt)
Definition: lstools_base.py:253
mbed_lstools.lstools_base.MbedLsToolsBase.__str__
def __str__(self)
Object to string casting.
Definition: lstools_base.py:489
object
mbed_lstools.lstools_base.MbedLsToolsBase.run_cli_process
def run_cli_process(cmd, shell=True)
Definition: lstools_base.py:697
mbed_lstools.lstools_base.MbedLsToolsBase.mock_manufacture_id
def mock_manufacture_id(self, mid, platform_name, oper='+')
Replace (or add if manufacture id doesn't exist) entry in self.manufacture_ids.
Definition: lstools_base.py:358
mbed_lstools.lstools_base.MbedLsToolsBase._fs_after_id_check
def _fs_after_id_check(self, device, filter_function, read_details_txt)
Definition: lstools_base.py:201
mbed_lstools.lstools_base.MbedLsToolsBase.RETARGET_FILE_NAME
string RETARGET_FILE_NAME
Definition: lstools_base.py:68
mbed_lstools.lstools_base.MbedLsToolsBase.parse_details_txt
def parse_details_txt(self, lines)
Definition: lstools_base.py:651
mbed_lstools.lstools_base.MbedLsToolsBase.find_candidates
def find_candidates(self)
Definition: lstools_base.py:98
mbed_lstools.lstools_base.MbedLsToolsBase.__init__
def __init__(self, list_unmounted=False, **kwargs)
Definition: lstools_base.py:79
mbed_lstools.lstools_base.MbedLsToolsBase.DETAILS_TXT_NAME
string DETAILS_TXT_NAME
Definition: lstools_base.py:69
mbed_lstools.platform_database.PlatformDatabase
Definition: platform_database.py:396
mbed_lstools.lstools_base.MbedLsToolsBase.mount_point_ready
def mount_point_ready(self, path)
Check if a mount point is ready for file operations.
Definition: lstools_base.py:689
mbed_lstools.lstools_base.MbedLsToolsBase._details_txt
def _details_txt(self, mount_point)
Load DETAILS.TXT to dictionary: DETAILS.TXT example: Version: 0226 Build: Aug 24 2015 17:06:30 Git Co...
Definition: lstools_base.py:620
mbed_lstools.lstools_base.MbedLsToolsBase.MOCK_FILE_NAME
string MOCK_FILE_NAME
Definition: lstools_base.py:67
mbed_lstools.lstools_base.MbedLsToolsBase.list_mbeds_ext
def list_mbeds_ext(self)
Function adds extra information for each mbed device.
Definition: lstools_base.py:110
mbed_lstools.lstools_base.MbedLsToolsBase.list_unmounted
list_unmounted
Definition: lstools_base.py:92
mbed_lstools.lstools_base.MbedLsToolsBase._target_id_from_htm
def _target_id_from_htm(self, line)
Extract Target id from htm line.
Definition: lstools_base.py:670
mbed_lstools.lstools_base.MbedLsToolsBase.list_platforms
def list_platforms(self)
Useful if you just want to know which platforms are currently available on the system.
Definition: lstools_base.py:447
mbed_lstools.lstools_base.MbedLsToolsBase.VENDOR_ID_DEVICE_TYPE_MAP
dictionary VENDOR_ID_DEVICE_TYPE_MAP
Definition: lstools_base.py:72
mbed_lstools.lstools_base.MbedLsToolsBase.scan_html_line_for_target_id
def scan_html_line_for_target_id(self, line)
Definition: lstools_base.py:667
mbed_lstools.lstools_base.MbedLsToolsBase.list_mbeds
def list_mbeds(self, fs_interaction=FSInteraction.BeforeFilter, filter_function=None, unique_names=False, read_details_txt=False)
Definition: lstools_base.py:118
mbed_lstools.lstools_base.MbedLsToolsBase.get_mbed_htm_comment_section_ver_build
def get_mbed_htm_comment_section_ver_build(self, line)
Definition: lstools_base.py:578
mbed_lstools.lstools_base.MbedLsToolsBase.plat_db
plat_db
Definition: lstools_base.py:90
mbed_lstools.lstools_base.MbedLsToolsBase.dummy_counter
dummy_counter
Definition: lstools_base.py:415
mbed_lstools.lstools_base.MbedLsToolsBase.list_manufacture_ids
def list_manufacture_ids(self)
Creates list of all available mappings for target_id -> Platform.
Definition: lstools_base.py:373
mbed_lstools.lstools_base.MbedLsToolsBase.retarget
def retarget(self)
Enable retargeting.
Definition: lstools_base.py:404
mbed_lstools.lstools_base.MbedLsToolsBase.get_supported_platforms
def get_supported_platforms(self, device_type=None)
Return a dictionary of supported target ids and the corresponding platform name.
Definition: lstools_base.py:433
mbed_lstools.lstools_base.MbedLsToolsBase._update_device_from_htm
def _update_device_from_htm(self, device)
Definition: lstools_base.py:320
mbed_lstools.lstools_base.MbedLsToolsBase._fs_before_id_check
def _fs_before_id_check(self, device, filter_function, read_details_txt)
Definition: lstools_base.py:189
mbed_lstools.lstools_base.MbedLsToolsBase.get_details_txt
def get_details_txt(self, mount_point)
Definition: lstools_base.py:617
mbed_lstools.lstools_base.MbedLsToolsBase
Definition: lstools_base.py:54
mbed_lstools.lstools_base.MbedLsToolsBase.get_htm_target_id
def get_htm_target_id(self, mount_point)
Definition: lstools_base.py:547
mbed_lstools.lstools_base.deprecated
def deprecated(reason)
Definition: lstools_base.py:38
mbed_lstools.lstools_base.MbedLsToolsBase.get_dummy_platform
def get_dummy_platform(self, platform_name)
Returns simple dummy platform.
Definition: lstools_base.py:412
mbed_lstools.lstools_base.FSInteraction
Definition: lstools_base.py:49