Skip to content

Commit

Permalink
Start a script-friendly CHIP REPL for python (project-chip#4696)
Browse files Browse the repository at this point in the history
* Define a chip-repl script that is intended to provide an interactive console against the python interfaces that chip provides

* Make GetAdapters work on chip repl

* Restyle fixes
  • Loading branch information
andy31415 committed Feb 10, 2021
1 parent 651cb99 commit 9947c03
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 19 deletions.
2 changes: 2 additions & 0 deletions src/controller/python/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pw_python_action("python") {
src_dir = "."
sources = [
"chip-device-ctrl.py",
"chip-repl.py",
"chip/ChipBleBase.py",
"chip/ChipBleUtility.py",
"chip/ChipBluezMgr.py",
Expand All @@ -76,6 +77,7 @@ pw_python_action("python") {
"chip/ChipTLV.py",
"chip/ChipUtility.py",
"chip/__init__.py",
"chip/ble/__init__.py",
]
},
{
Expand Down
45 changes: 29 additions & 16 deletions src/controller/python/build-chip-wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,23 @@

args = parser.parse_args()

class InstalledScriptInfo:
"""Information holder about a script that is to be installed."""

def __init__(self, name):
self.name = name
self.installName = os.path.splitext(name)[0]


chipDLLName = '_ChipDeviceCtrl.so'
deviceManagerShellName = 'chip-device-ctrl.py'
chipControllerShellInstalledName = os.path.splitext(deviceManagerShellName)[0]
packageName = args.package_name
chipPackageVer = args.build_number

installScripts = [
InstalledScriptInfo('chip-device-ctrl.py'),
InstalledScriptInfo('chip-repl.py'),
]

# Record the current directory at the start of execution.
curDir = os.curdir

Expand Down Expand Up @@ -85,25 +96,25 @@
os.makedirs(os.path.dirname(dstFile), exist_ok=True)
shutil.copyfile(srcFile, dstFile)

os.rename(os.path.join(tmpDir, deviceManagerShellName),
os.path.join(tmpDir, chipControllerShellInstalledName))
for script in installScripts:
os.rename(os.path.join(tmpDir, script.name),
os.path.join(tmpDir, script.installName))

# Define a custom version of the bdist_wheel command that configures the
# resultant wheel as platform-specific (i.e. not "pure").
class bdist_wheel_override(bdist_wheel):
def finalize_options(self):
bdist_wheel.finalize_options(self)
self.root_is_pure = False

requiredPackages = []

requiredPackages.append('ipython')

# Select required packages based on the target system.
if platform.system() == 'Linux':
requiredPackages = [
'dbus-python',
'six',
'pygobject',
]
else:
requiredPackages = []
requiredPackages.append('dbus-python')
requiredPackages.append('six')
requiredPackages.append('pygobject')

#
# Build the chip package...
Expand All @@ -126,7 +137,8 @@ def finalize_options(self):
],
python_requires='>=2.7',
packages=[
packageName # Arrange to install a package named "chip"
'chip',
'chip.ble',
],
package_dir={
'':tmpDir, # By default, look in the tmp directory for packages/modules to be included.
Expand All @@ -136,9 +148,10 @@ def finalize_options(self):
chipDLLName # Include the wrapper DLL as package data in the "chip" package.
]
},
scripts=[ # Install the Device controller Shell as an executable script in the 'bin' directory.
os.path.join(tmpDir, chipControllerShellInstalledName)
],
scripts = [name for name in map(
lambda script: os.path.join(tmpDir, script.installName),
installScripts
)],
install_requires=requiredPackages,
options={
'bdist_wheel':{
Expand Down
3 changes: 0 additions & 3 deletions src/controller/python/chip-device-ctrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@

from __future__ import absolute_import
from __future__ import print_function
from chip import ChipStack
from chip import ChipDeviceCtrl
from chip import ChipExceptions
from builtins import range
import sys
import os
import platform
Expand All @@ -38,7 +36,6 @@
import textwrap
import string
from cmd import Cmd
from six.moves import range
from chip.ChipBleUtility import FAKE_CONN_OBJ_VALUE

# Extend sys.path with one or more directories, relative to the location of the
Expand Down
38 changes: 38 additions & 0 deletions src/controller/python/chip-repl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env python

#
# Copyright (c) 2021 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from IPython import embed
import chip

def main():
# The chip import at the top level will be visible in the ipython REPL.
embed(header = '''
Welcome to the CHIP python REPL utilty.
Usage examples:
######## List available BLE adapters #########
for adapter in chip.GetBleAdapters():
print(adapter)
'''.strip())

if __name__ == "__main__":
main()
9 changes: 9 additions & 0 deletions src/controller/python/chip/ChipBluezMgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,15 @@ def ble_adapter_select(self, identifier=None):
self.adapter.Powered(False)
self.adapter.Powered(True)

def get_adapters(self):
return [
BluezDbusAdapter(p["object"], self.bluez, self.bus, self.logger)
for p in get_bluez_objects(
self.bluez, self.bus, ADAPTER_INTERFACE, "/org/bluez"
)
]


def ble_adapter_print(self):
try:
adapters = [
Expand Down
2 changes: 2 additions & 0 deletions src/controller/python/chip/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@
#

"""Provides Python APIs for CHIP."""

from chip.ble import GetBleAdapters
72 changes: 72 additions & 0 deletions src/controller/python/chip/ble/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""BLE-related functionality within CHIP"""

from chip import ChipDeviceCtrl
import sys
import platform

class Adapter:
"""Generic exposed adapter information."""

def __init__(self, name, macAddress):
self.name = name
self.macAddress = macAddress

def __str__(self):
return 'chip.ble.Adapter(%s, %s)' % (self.name, self.macAddress)

if platform.system() == 'Darwin':
from chip.ChipCoreBluetoothMgr import CoreBluetoothManager as BleManager

def ConvertNativeAdapter(nativeAdapter):
raise NotImplementedError('Not implemented for Darwin')

elif sys.platform.startswith('linux'):
from chip.ChipBluezMgr import BluezManager as BleManager

def ConvertNativeAdapter(nativeAdapter):
return Adapter(name = str(nativeAdapter.path), macAddress = str(nativeAdapter.Address))

class LazyHandles(object):
"""Contains a handle to an underlying BLE manager."""

def __init__(self):
self._deviceController = None
self._bleManager = None

@property
def deviceController(self):
if self._deviceController is None:
self._deviceController = ChipDeviceCtrl.ChipDeviceController()
return self._deviceController

@property
def bleManager(self):
if self._bleManager is None:
self._bleManager = BleManager(self.deviceController)
return self._bleManager

def GetAdapters(self):
"""Return available BLE adapters on this platform."""
return [ConvertNativeAdapter(a) for a in self.bleManager.get_adapters()]


lazyHandles = LazyHandles()

def GetBleAdapters():
return lazyHandles.GetAdapters()

__all__ = [
"GetBleAdapters",
]

0 comments on commit 9947c03

Please sign in to comment.