From a3f3c9dfb6b7dfdd260c9c2ac090ec666c105f98 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 4 Nov 2023 10:52:49 +0430 Subject: [PATCH 01/18] Update __init__.py --- dronekit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index bc05a7098..1b0f88ff0 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -2917,7 +2917,7 @@ def decorated_thr_min_callback(self, attr_name, value): return super(Parameters, self).on_attribute(attr_name, *args, **kwargs) -class Command(mavutil.mavlink.MAVLink_mission_item_message): +class Command(mavutil.mavlink.MAVLink_mission_item_int_message): """ A waypoint object. From 40c074cb818abb971016b1784c7c72a22557bf18 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Wed, 8 Nov 2023 12:22:07 +0430 Subject: [PATCH 02/18] Fixed Error (WARNING:autopilot:got MISSION_REQUEST; use MISSION_REQUEST_INT!) --- dronekit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index 1b0f88ff0..e2bf6a403 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -1309,7 +1309,7 @@ def listener(self, name, msg): self.notify_attribute_listeners('commands', self.commands) # Waypoint send to master - @self.on_message(['WAYPOINT_REQUEST', 'MISSION_REQUEST']) + @self.on_message(['WAYPOINT_REQUEST', 'MISSION_REQUEST_INT']) def listener(self, name, msg): if self._wp_uploaded is not None: wp = self._wploader.wp(msg.seq) From 8bc3cef8e970c4a51b5e1605757e66c4ea05c6a5 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Thu, 9 Nov 2023 10:05:16 +0430 Subject: [PATCH 03/18] Fixed exception when UDP connection was forcibly closed. --- dronekit/mavlink.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dronekit/mavlink.py b/dronekit/mavlink.py index d87f93ae5..166f5189a 100644 --- a/dronekit/mavlink.py +++ b/dronekit/mavlink.py @@ -72,7 +72,10 @@ def recv(self, n=None): if e.errno in [errno.EAGAIN, errno.EWOULDBLOCK, errno.ECONNREFUSED]: return "" if self.udp_server: - self.addresses.add(new_addr) + try: + self.addresses.add(new_addr) + except: + return "" elif self.broadcast: self.addresses = {new_addr} return data From 8e89a9cea9b526b65b288a551d46ebd12fd95e83 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 11 Nov 2023 09:46:59 +0430 Subject: [PATCH 04/18] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 49d7477e2..1b39d9329 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ import setuptools import os -version = '2.9.2' +version = '2.9.3' with open(os.path.join(os.path.dirname(__file__), 'README.md')) as f: LongDescription = f.read() From 72ec5d748f5632d53358c848c4ee603aa8971b29 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 11 Nov 2023 10:00:50 +0430 Subject: [PATCH 05/18] Fixed the encoding error for Python 3.x. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1b39d9329..101456bca 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ version = '2.9.3' -with open(os.path.join(os.path.dirname(__file__), 'README.md')) as f: +with open(os.path.join(os.path.dirname(__file__), 'README.md'), encoding="utf-8") as f: LongDescription = f.read() setuptools.setup( From a788e3b8cac74b3b97ec68eb73c5c965a5d7a2cb Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 11 Nov 2023 10:51:01 +0430 Subject: [PATCH 06/18] Create python-publish.yml --- .github/workflows/python-publish.yml | 39 ++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/python-publish.yml diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 000000000..bdaab28a4 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,39 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Upload Python Package + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} From 397f510c44fdd84a775542d854fa495368b2708c Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 11 Nov 2023 10:59:53 +0430 Subject: [PATCH 07/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f024a0b6f..5d02ece21 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ DroneKit-Python helps you create powerful apps for UAVs. # ⚠️ ATTENTION: MAINTAINERS NEEDED ⚠️ -Hey it's true this project is not very active, but it could be with your help. We are looking for maintainers interested in keeping the project alive by keep up with CI and PRs. If you are interested in helping please apply by [creating an issue]([url](https://github.com/dronekit/dronekit-python/issues/new)) and listing the reasons why you would like to help, in return we will be granting committer access to folks who are truly interested in helping. +Hey it's true this project is not very active, but it could be with your help. We are looking for maintainers interested in keeping the project alive by keep up with CI and PRs. If you are interested in helping please apply by [creating an issue]([url](https://github.com/dronekit/dronekit-python/issues/new)) and listing the reasons why you would like to help, in return we will be granting committer access to folks who are truly interested in helping.. ## Overview From 3da4e3b9cfa58ec4925701592331591829b59081 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 11 Nov 2023 13:49:08 +0430 Subject: [PATCH 08/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d02ece21..f024a0b6f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ DroneKit-Python helps you create powerful apps for UAVs. # ⚠️ ATTENTION: MAINTAINERS NEEDED ⚠️ -Hey it's true this project is not very active, but it could be with your help. We are looking for maintainers interested in keeping the project alive by keep up with CI and PRs. If you are interested in helping please apply by [creating an issue]([url](https://github.com/dronekit/dronekit-python/issues/new)) and listing the reasons why you would like to help, in return we will be granting committer access to folks who are truly interested in helping.. +Hey it's true this project is not very active, but it could be with your help. We are looking for maintainers interested in keeping the project alive by keep up with CI and PRs. If you are interested in helping please apply by [creating an issue]([url](https://github.com/dronekit/dronekit-python/issues/new)) and listing the reasons why you would like to help, in return we will be granting committer access to folks who are truly interested in helping. ## Overview From 6be1b4070d9b8d85f03982e9fd3b83867d2f167b Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sun, 12 Nov 2023 10:56:06 +0430 Subject: [PATCH 09/18] Fixed the issue where the exception was being displayed twice when there was no heartbeat for 30 seconds. --- dronekit/mavlink.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dronekit/mavlink.py b/dronekit/mavlink.py index 166f5189a..3ab9914ae 100644 --- a/dronekit/mavlink.py +++ b/dronekit/mavlink.py @@ -248,7 +248,8 @@ def mavlink_thread_in(): ) except APIException as e: - self._logger.exception('Exception in MAVLink input loop') + #self._logger.exception('Exception in MAVLink input loop') + self._logger.error('%s' % str(e)) self._alive = False self.master.close() self._death_error = e From f5670a1329828190dbc3ab2a7af72edc2d8c10e5 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sun, 12 Nov 2023 11:17:36 +0430 Subject: [PATCH 10/18] Fixed the issue where the exception was being displayed twice when there was no heartbeat for 30 seconds. --- dronekit/mavlink.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dronekit/mavlink.py b/dronekit/mavlink.py index 3ab9914ae..a9ed962e7 100644 --- a/dronekit/mavlink.py +++ b/dronekit/mavlink.py @@ -249,7 +249,7 @@ def mavlink_thread_in(): except APIException as e: #self._logger.exception('Exception in MAVLink input loop') - self._logger.error('%s' % str(e)) + self._logger.warning('%s' % str(e)) self._alive = False self.master.close() self._death_error = e From 4b2f63abb1dc1c1bcfb362ec71803f78e6354836 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 18 Nov 2023 09:22:19 +0430 Subject: [PATCH 11/18] Channels: fix wrong key type --- dronekit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index e2bf6a403..39fd690bd 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -816,10 +816,10 @@ def __len__(self): def _update_channel(self, channel, value): # If we have channels on different ports, we expand the Channels # object to support them. - channel = int(channel) self._readonly = False self[channel] = value self._readonly = True + channel = int(channel) self._count = max(self._count, channel) @property From d8b0faf8acbda86d87bd9ad93067725357b70366 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Thu, 7 Dec 2023 11:23:36 +0430 Subject: [PATCH 12/18] Changed MISSION_ITEM into MISSION_ITEM_INT --- dronekit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index 39fd690bd..c845c7a28 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -1286,7 +1286,7 @@ def listener(self, name, msg): self._home_location = LocationGlobal(msg.latitude / 1.0e7, msg.longitude / 1.0e7, msg.altitude / 1000.0) self.notify_attribute_listeners('home_location', self.home_location, cache=True) - @self.on_message(['WAYPOINT', 'MISSION_ITEM']) + @self.on_message(['WAYPOINT', 'MISSION_ITEM_INT']) def listener(self, name, msg): if not self._wp_loaded: if msg.seq == 0: From 7c1792617cdc3bd33044376aad42ad9fe140aab3 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Thu, 7 Dec 2023 11:24:12 +0430 Subject: [PATCH 13/18] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 101456bca..29638bfb8 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ import setuptools import os -version = '2.9.3' +version = '2.9.3.1' with open(os.path.join(os.path.dirname(__file__), 'README.md'), encoding="utf-8") as f: LongDescription = f.read() From e52e4be3ca2c16a9ea8476096967b5bffd6eabef Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sat, 9 Dec 2023 09:47:22 +0430 Subject: [PATCH 14/18] Update __init__.py --- dronekit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index c845c7a28..39fd690bd 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -1286,7 +1286,7 @@ def listener(self, name, msg): self._home_location = LocationGlobal(msg.latitude / 1.0e7, msg.longitude / 1.0e7, msg.altitude / 1000.0) self.notify_attribute_listeners('home_location', self.home_location, cache=True) - @self.on_message(['WAYPOINT', 'MISSION_ITEM_INT']) + @self.on_message(['WAYPOINT', 'MISSION_ITEM']) def listener(self, name, msg): if not self._wp_loaded: if msg.seq == 0: From 0b7bbc5e46f44c5ad20a7dba01d106ec60ba5021 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Mon, 1 Jan 2024 10:44:28 +0430 Subject: [PATCH 15/18] Update __init__.py --- dronekit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index 39fd690bd..6a31ef01b 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -1309,7 +1309,7 @@ def listener(self, name, msg): self.notify_attribute_listeners('commands', self.commands) # Waypoint send to master - @self.on_message(['WAYPOINT_REQUEST', 'MISSION_REQUEST_INT']) + @self.on_message(['WAYPOINT_REQUEST', 'MISSION_REQUEST']) def listener(self, name, msg): if self._wp_uploaded is not None: wp = self._wploader.wp(msg.seq) From 2e37ebe143c83a730905bec7c88b5a7255aaa4c3 Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sun, 26 May 2024 12:04:52 +0430 Subject: [PATCH 16/18] Update __init__.py --- dronekit/__init__.py | 81 ++++++++++---------------------------------- 1 file changed, 18 insertions(+), 63 deletions(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index 6a31ef01b..9a32bc4cb 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -32,15 +32,7 @@ ---- """ -import sys import collections - -# Python3.10 removed MutableMapping from collections: -if sys.version_info.major == 3 and sys.version_info.minor >= 10: - from collections.abc import MutableMapping -else: - from collections import MutableMapping - import copy import logging import math @@ -228,25 +220,6 @@ def __str__(self): return "GPSInfo:fix=%s,num_sat=%s" % (self.fix_type, self.satellites_visible) -class Wind(object): - """ - Wind information - - An object of this type is returned by :py:attr: `Vehicle.wind`. - - :param wind_direction: Wind direction in degrees - :param wind_speed: Wind speed in m/s - :param wind_speed_z: vertical wind speed in m/s - """ - def __init__(self, wind_direction, wind_speed, wind_speed_z): - self.wind_direction = wind_direction - self.wind_speed = wind_speed - self.wind_speed_z = wind_speed_z - - def __str__(self): - return "Wind: wind direction: {}, wind speed: {}, wind speed z: {}".format(self.wind_direction, self.wind_speed, self.wind_speed_z) - - class Battery(object): """ System battery information. @@ -816,10 +789,10 @@ def __len__(self): def _update_channel(self, channel, value): # If we have channels on different ports, we expand the Channels # object to support them. + channel = int(channel) self._readonly = False self[channel] = value self._readonly = True - channel = int(channel) self._count = max(self._count, channel) @property @@ -1084,19 +1057,6 @@ def listener(_, msg): self._vy = None self._vz = None - - self._wind_direction = None - self._wind_speed = None - self._wind_speed_z = None - - @self.on_message('WIND') - def listener(self,name, m): - """ WIND {direction : -180.0, speed : 0.0, speed_z : 0.0} """ - self._wind_direction = m.direction - self._wind_speed = m.speed - self._wind_speed_z = m.speed_z - - @self.on_message('STATUSTEXT') def statustext_listener(self, name, m): # Log the STATUSTEXT on the autopilot logger, with the correct severity @@ -1182,17 +1142,21 @@ def listener(vehicle, name, m): # All keys are strings. self._channels = Channels(self, 8) - @self.on_message(['RC_CHANNELS_RAW', 'RC_CHANNELS']) + @self.on_message('RC_CHANNELS_RAW') def listener(self, name, m): def set_rc(chnum, v): '''Private utility for handling rc channel messages''' # use port to allow ch nums greater than 8 - port = 0 if name == "RC_CHANNELS" else m.port - self._channels._update_channel(str(port * 8 + chnum), v) - - for i in range(1, (18 if name == "RC_CHANNELS" else 8)+1): - set_rc(i, getattr(m, "chan{}_raw".format(i))) - + self._channels._update_channel(str(m.port * 8 + chnum), v) + + set_rc(1, m.chan1_raw) + set_rc(2, m.chan2_raw) + set_rc(3, m.chan3_raw) + set_rc(4, m.chan4_raw) + set_rc(5, m.chan5_raw) + set_rc(6, m.chan6_raw) + set_rc(7, m.chan7_raw) + set_rc(8, m.chan8_raw) self.notify_attribute_listeners('channels', self.channels) self._voltage = None @@ -1249,7 +1213,7 @@ def listener(self, name, m): @self.on_message('HEARTBEAT') def listener(self, name, m): # ignore groundstations - if m.type == mavutil.mavlink.MAV_TYPE_GCS or (not self._handler.master.probably_vehicle_heartbeat(m)): + if m.type == mavutil.mavlink.MAV_TYPE_GCS: return self._armed = (m.base_mode & mavutil.mavlink.MAV_MODE_FLAG_SAFETY_ARMED) != 0 self.notify_attribute_listeners('armed', self.armed, cache=True) @@ -1286,7 +1250,7 @@ def listener(self, name, msg): self._home_location = LocationGlobal(msg.latitude / 1.0e7, msg.longitude / 1.0e7, msg.altitude / 1000.0) self.notify_attribute_listeners('home_location', self.home_location, cache=True) - @self.on_message(['WAYPOINT', 'MISSION_ITEM']) + @self.on_message(['WAYPOINT', 'MISSION_ITEM', 'MISSION_ITEM_INT']) def listener(self, name, msg): if not self._wp_loaded: if msg.seq == 0: @@ -1309,7 +1273,7 @@ def listener(self, name, msg): self.notify_attribute_listeners('commands', self.commands) # Waypoint send to master - @self.on_message(['WAYPOINT_REQUEST', 'MISSION_REQUEST']) + @self.on_message(['WAYPOINT_REQUEST', 'MISSION_REQUEST', 'MISSION_REQUEST_INT']) def listener(self, name, msg): if self._wp_uploaded is not None: wp = self._wploader.wp(msg.seq) @@ -1413,7 +1377,7 @@ def listener(_): @self.on_message(['HEARTBEAT']) def listener(self, name, msg): # ignore groundstations - if msg.type == mavutil.mavlink.MAV_TYPE_GCS or (not self._handler.master.probably_vehicle_heartbeat(msg)): + if msg.type == mavutil.mavlink.MAV_TYPE_GCS: return self._heartbeat_system = msg.get_srcSystem() self._heartbeat_lastreceived = monotonic.monotonic() @@ -1718,15 +1682,6 @@ def listener(self, attr_name, value): """ return self._location - @property - def wind(self): - """ - Current wind status (:pu:class: `Wind`) - """ - if self._wind_direction is None or self._wind_speed is None or self._wind_speed_z is None: - return None - return Wind(self._wind_direction, self._wind_speed, self._wind_speed_z) - @property def battery(self): """ @@ -2589,7 +2544,7 @@ def listener(vehicle, name, m): @vehicle.on_message('MOUNT_ORIENTATION') def listener(vehicle, name, m): - self._pitch = m.pitch + self._pitch = m.pitch self._roll = m.roll self._yaw = m.yaw vehicle.notify_attribute_listeners('gimbal', vehicle.gimbal) @@ -2731,7 +2686,7 @@ def __str__(self): return "Gimbal: pitch={0}, roll={1}, yaw={2}".format(self.pitch, self.roll, self.yaw) -class Parameters(MutableMapping, HasObservers): +class Parameters(collections.abc.MutableMapping, HasObservers): """ This object is used to get and set the values of named parameters for a vehicle. See the following links for information about the supported parameters for each platform: `Copter Parameters `_, From ae043d15a5b897d4a29f36fe48e529cb4f809d4e Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Sun, 26 May 2024 12:25:42 +0430 Subject: [PATCH 17/18] Fixed got MISSION_REQUEST; use MISSION_REQUEST_INT! --- dronekit/__init__.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/dronekit/__init__.py b/dronekit/__init__.py index 9a32bc4cb..38575a722 100644 --- a/dronekit/__init__.py +++ b/dronekit/__init__.py @@ -1243,7 +1243,12 @@ def listener(self, name, msg): if not self._wp_loaded: self._wploader.clear() self._wploader.expected_count = msg.count - self._master.waypoint_request_send(0) + # self._master.waypoint_request_send(0) + self._master.mav.mission_request_int_send( + target_system=self._master.target_system, + target_component=self._master.target_component, + seq=0 # Sequence number of the mission item to request + ) @self.on_message(['HOME_POSITION']) def listener(self, name, msg): @@ -1267,7 +1272,12 @@ def listener(self, name, msg): self._wploader.add(msg) if msg.seq + 1 < self._wploader.expected_count: - self._master.waypoint_request_send(msg.seq + 1) + # self._master.waypoint_request_send(msg.seq + 1) + self._master.mav.mission_request_int_send( + target_system=self._master.target_system, + target_component=self._master.target_component, + seq=msg.seq + 1 # Sequence number of the mission item to request + ) else: self._wp_loaded = True self.notify_attribute_listeners('commands', self.commands) @@ -2188,7 +2198,7 @@ def simple_goto(self, location, airspeed=None, groundspeed=None): else: raise ValueError('Expecting location to be LocationGlobal or LocationGlobalRelative.') - self._master.mav.mission_item_send(0, 0, 0, frame, + self._master.mav.mission_item_int_send(0, 0, 0, frame, mavutil.mavlink.MAV_CMD_NAV_WAYPOINT, 2, 0, 0, 0, 0, 0, location.lat, location.lon, alt) From ccf151060a827ca529698a392fcef13e888561ea Mon Sep 17 00:00:00 2001 From: Shafiq Sadat Date: Thu, 30 May 2024 10:27:18 +0430 Subject: [PATCH 18/18] Update mavlink.py --- dronekit/mavlink.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dronekit/mavlink.py b/dronekit/mavlink.py index a9ed962e7..2623194b5 100644 --- a/dronekit/mavlink.py +++ b/dronekit/mavlink.py @@ -248,8 +248,8 @@ def mavlink_thread_in(): ) except APIException as e: - #self._logger.exception('Exception in MAVLink input loop') - self._logger.warning('%s' % str(e)) + self._logger.exception('Exception in MAVLink input loop') + self._logger.error('%s' % str(e)) self._alive = False self.master.close() self._death_error = e