Skip to content

Commit 9947c03

Browse files
authored
Start a script-friendly CHIP REPL for python (#4696)
* 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
1 parent 651cb99 commit 9947c03

File tree

7 files changed

+152
-19
lines changed

7 files changed

+152
-19
lines changed

src/controller/python/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pw_python_action("python") {
6565
src_dir = "."
6666
sources = [
6767
"chip-device-ctrl.py",
68+
"chip-repl.py",
6869
"chip/ChipBleBase.py",
6970
"chip/ChipBleUtility.py",
7071
"chip/ChipBluezMgr.py",
@@ -76,6 +77,7 @@ pw_python_action("python") {
7677
"chip/ChipTLV.py",
7778
"chip/ChipUtility.py",
7879
"chip/__init__.py",
80+
"chip/ble/__init__.py",
7981
]
8082
},
8183
{

src/controller/python/build-chip-wheel.py

+29-16
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,23 @@
4242

4343
args = parser.parse_args()
4444

45+
class InstalledScriptInfo:
46+
"""Information holder about a script that is to be installed."""
47+
48+
def __init__(self, name):
49+
self.name = name
50+
self.installName = os.path.splitext(name)[0]
51+
52+
4553
chipDLLName = '_ChipDeviceCtrl.so'
46-
deviceManagerShellName = 'chip-device-ctrl.py'
47-
chipControllerShellInstalledName = os.path.splitext(deviceManagerShellName)[0]
4854
packageName = args.package_name
4955
chipPackageVer = args.build_number
5056

57+
installScripts = [
58+
InstalledScriptInfo('chip-device-ctrl.py'),
59+
InstalledScriptInfo('chip-repl.py'),
60+
]
61+
5162
# Record the current directory at the start of execution.
5263
curDir = os.curdir
5364

@@ -85,25 +96,25 @@
8596
os.makedirs(os.path.dirname(dstFile), exist_ok=True)
8697
shutil.copyfile(srcFile, dstFile)
8798

88-
os.rename(os.path.join(tmpDir, deviceManagerShellName),
89-
os.path.join(tmpDir, chipControllerShellInstalledName))
99+
for script in installScripts:
100+
os.rename(os.path.join(tmpDir, script.name),
101+
os.path.join(tmpDir, script.installName))
90102

91103
# Define a custom version of the bdist_wheel command that configures the
92104
# resultant wheel as platform-specific (i.e. not "pure").
93105
class bdist_wheel_override(bdist_wheel):
94106
def finalize_options(self):
95107
bdist_wheel.finalize_options(self)
96108
self.root_is_pure = False
109+
110+
requiredPackages = []
111+
112+
requiredPackages.append('ipython')
97113

98-
# Select required packages based on the target system.
99114
if platform.system() == 'Linux':
100-
requiredPackages = [
101-
'dbus-python',
102-
'six',
103-
'pygobject',
104-
]
105-
else:
106-
requiredPackages = []
115+
requiredPackages.append('dbus-python')
116+
requiredPackages.append('six')
117+
requiredPackages.append('pygobject')
107118

108119
#
109120
# Build the chip package...
@@ -126,7 +137,8 @@ def finalize_options(self):
126137
],
127138
python_requires='>=2.7',
128139
packages=[
129-
packageName # Arrange to install a package named "chip"
140+
'chip',
141+
'chip.ble',
130142
],
131143
package_dir={
132144
'':tmpDir, # By default, look in the tmp directory for packages/modules to be included.
@@ -136,9 +148,10 @@ def finalize_options(self):
136148
chipDLLName # Include the wrapper DLL as package data in the "chip" package.
137149
]
138150
},
139-
scripts=[ # Install the Device controller Shell as an executable script in the 'bin' directory.
140-
os.path.join(tmpDir, chipControllerShellInstalledName)
141-
],
151+
scripts = [name for name in map(
152+
lambda script: os.path.join(tmpDir, script.installName),
153+
installScripts
154+
)],
142155
install_requires=requiredPackages,
143156
options={
144157
'bdist_wheel':{

src/controller/python/chip-device-ctrl.py

-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@
2525

2626
from __future__ import absolute_import
2727
from __future__ import print_function
28-
from chip import ChipStack
2928
from chip import ChipDeviceCtrl
3029
from chip import ChipExceptions
31-
from builtins import range
3230
import sys
3331
import os
3432
import platform
@@ -38,7 +36,6 @@
3836
import textwrap
3937
import string
4038
from cmd import Cmd
41-
from six.moves import range
4239
from chip.ChipBleUtility import FAKE_CONN_OBJ_VALUE
4340

4441
# Extend sys.path with one or more directories, relative to the location of the

src/controller/python/chip-repl.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env python
2+
3+
#
4+
# Copyright (c) 2021 Project CHIP Authors
5+
# All rights reserved.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
from IPython import embed
21+
import chip
22+
23+
def main():
24+
# The chip import at the top level will be visible in the ipython REPL.
25+
embed(header = '''
26+
Welcome to the CHIP python REPL utilty.
27+
28+
Usage examples:
29+
30+
######## List available BLE adapters #########
31+
32+
for adapter in chip.GetBleAdapters():
33+
print(adapter)
34+
35+
'''.strip())
36+
37+
if __name__ == "__main__":
38+
main()

src/controller/python/chip/ChipBluezMgr.py

+9
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,15 @@ def ble_adapter_select(self, identifier=None):
833833
self.adapter.Powered(False)
834834
self.adapter.Powered(True)
835835

836+
def get_adapters(self):
837+
return [
838+
BluezDbusAdapter(p["object"], self.bluez, self.bus, self.logger)
839+
for p in get_bluez_objects(
840+
self.bluez, self.bus, ADAPTER_INTERFACE, "/org/bluez"
841+
)
842+
]
843+
844+
836845
def ble_adapter_print(self):
837846
try:
838847
adapters = [

src/controller/python/chip/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@
2222
#
2323

2424
"""Provides Python APIs for CHIP."""
25+
26+
from chip.ble import GetBleAdapters
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License");
2+
# you may not use this file except in compliance with the License.
3+
# You may obtain a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS,
9+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# See the License for the specific language governing permissions and
11+
# limitations under the License.
12+
13+
"""BLE-related functionality within CHIP"""
14+
15+
from chip import ChipDeviceCtrl
16+
import sys
17+
import platform
18+
19+
class Adapter:
20+
"""Generic exposed adapter information."""
21+
22+
def __init__(self, name, macAddress):
23+
self.name = name
24+
self.macAddress = macAddress
25+
26+
def __str__(self):
27+
return 'chip.ble.Adapter(%s, %s)' % (self.name, self.macAddress)
28+
29+
if platform.system() == 'Darwin':
30+
from chip.ChipCoreBluetoothMgr import CoreBluetoothManager as BleManager
31+
32+
def ConvertNativeAdapter(nativeAdapter):
33+
raise NotImplementedError('Not implemented for Darwin')
34+
35+
elif sys.platform.startswith('linux'):
36+
from chip.ChipBluezMgr import BluezManager as BleManager
37+
38+
def ConvertNativeAdapter(nativeAdapter):
39+
return Adapter(name = str(nativeAdapter.path), macAddress = str(nativeAdapter.Address))
40+
41+
class LazyHandles(object):
42+
"""Contains a handle to an underlying BLE manager."""
43+
44+
def __init__(self):
45+
self._deviceController = None
46+
self._bleManager = None
47+
48+
@property
49+
def deviceController(self):
50+
if self._deviceController is None:
51+
self._deviceController = ChipDeviceCtrl.ChipDeviceController()
52+
return self._deviceController
53+
54+
@property
55+
def bleManager(self):
56+
if self._bleManager is None:
57+
self._bleManager = BleManager(self.deviceController)
58+
return self._bleManager
59+
60+
def GetAdapters(self):
61+
"""Return available BLE adapters on this platform."""
62+
return [ConvertNativeAdapter(a) for a in self.bleManager.get_adapters()]
63+
64+
65+
lazyHandles = LazyHandles()
66+
67+
def GetBleAdapters():
68+
return lazyHandles.GetAdapters()
69+
70+
__all__ = [
71+
"GetBleAdapters",
72+
]

0 commit comments

Comments
 (0)