simconnect-H 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/LICENSE +1 -1
- {simconnect_h-0.2.0/simconnect_H.egg-info → simconnect_h-0.2.2}/PKG-INFO +2 -2
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/README.md +1 -1
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/pyproject.toml +1 -1
- {simconnect_h-0.2.0 → simconnect_h-0.2.2/simconnect_H.egg-info}/PKG-INFO +2 -2
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/simconnect_native/__init__.py +71 -55
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/setup.cfg +0 -0
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/simconnect_H.egg-info/SOURCES.txt +0 -0
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/simconnect_H.egg-info/dependency_links.txt +0 -0
- {simconnect_h-0.2.0 → simconnect_h-0.2.2}/simconnect_H.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simconnect-H
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: 原生 ctypes SimConnect 库 — 零外部依赖,直接加载 SimConnect.dll 与 MSFS 通讯
|
|
5
5
|
Author-email: HuJie <150501351+hjznb887@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -164,7 +164,7 @@ with SimConnect() as sc:
|
|
|
164
164
|
| ------ | ------ |
|
|
165
165
|
| `find_simconnect_dll()` | 自动搜索 SimConnect.dll 路径 |
|
|
166
166
|
| `read_data_value(pData, datatype=0)` | 从 dispatch 回调中读取指定类型数据 |
|
|
167
|
-
| `__version__` | 当前库版本 `"0.2.
|
|
167
|
+
| `__version__` | 当前库版本 `"0.2.2"` |
|
|
168
168
|
|
|
169
169
|
## 许可证
|
|
170
170
|
|
|
@@ -145,7 +145,7 @@ with SimConnect() as sc:
|
|
|
145
145
|
| ------ | ------ |
|
|
146
146
|
| `find_simconnect_dll()` | 自动搜索 SimConnect.dll 路径 |
|
|
147
147
|
| `read_data_value(pData, datatype=0)` | 从 dispatch 回调中读取指定类型数据 |
|
|
148
|
-
| `__version__` | 当前库版本 `"0.2.
|
|
148
|
+
| `__version__` | 当前库版本 `"0.2.2"` |
|
|
149
149
|
|
|
150
150
|
## 许可证
|
|
151
151
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: simconnect-H
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: 原生 ctypes SimConnect 库 — 零外部依赖,直接加载 SimConnect.dll 与 MSFS 通讯
|
|
5
5
|
Author-email: HuJie <150501351+hjznb887@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -164,7 +164,7 @@ with SimConnect() as sc:
|
|
|
164
164
|
| ------ | ------ |
|
|
165
165
|
| `find_simconnect_dll()` | 自动搜索 SimConnect.dll 路径 |
|
|
166
166
|
| `read_data_value(pData, datatype=0)` | 从 dispatch 回调中读取指定类型数据 |
|
|
167
|
-
| `__version__` | 当前库版本 `"0.2.
|
|
167
|
+
| `__version__` | 当前库版本 `"0.2.2"` |
|
|
168
168
|
|
|
169
169
|
## 许可证
|
|
170
170
|
|
|
@@ -30,6 +30,7 @@ import os
|
|
|
30
30
|
import time
|
|
31
31
|
import logging
|
|
32
32
|
import threading
|
|
33
|
+
from typing import Callable, Optional, Any, Tuple
|
|
33
34
|
from ctypes import (c_ulong, c_float, c_char_p, c_double, c_void_p, c_int32, c_int16, c_int8,
|
|
34
35
|
cast, POINTER, sizeof as c_sizeof, Structure, WinDLL, byref)
|
|
35
36
|
from ctypes.wintypes import HANDLE, DWORD, HRESULT
|
|
@@ -69,7 +70,7 @@ logger = logging.getLogger(__name__)
|
|
|
69
70
|
# 版本
|
|
70
71
|
# ═══════════════════════════════════════════════════
|
|
71
72
|
|
|
72
|
-
__version__ = "0.2.
|
|
73
|
+
__version__ = "0.2.2"
|
|
73
74
|
|
|
74
75
|
# ═══════════════════════════════════════════════════
|
|
75
76
|
# 常量
|
|
@@ -201,7 +202,7 @@ MSFS_EVENTS = {
|
|
|
201
202
|
# DLL 查找
|
|
202
203
|
# ═══════════════════════════════════════════════════
|
|
203
204
|
|
|
204
|
-
def find_simconnect_dll():
|
|
205
|
+
def find_simconnect_dll() -> str:
|
|
205
206
|
"""查找 SimConnect.dll 位置。
|
|
206
207
|
|
|
207
208
|
搜索顺序:
|
|
@@ -241,7 +242,7 @@ def find_simconnect_dll():
|
|
|
241
242
|
# 模块级便利函数
|
|
242
243
|
# ═══════════════════════════════════════════════════
|
|
243
244
|
|
|
244
|
-
def read_data_value(pData, datatype=0):
|
|
245
|
+
def read_data_value(pData: Any, datatype: int = 0) -> Any:
|
|
245
246
|
"""从 dispatch 回调的 pData 中读取指定类型的数据。
|
|
246
247
|
|
|
247
248
|
用法:
|
|
@@ -287,38 +288,38 @@ class SimConnect:
|
|
|
287
288
|
# ── 属性 ──────────────────────────────────────
|
|
288
289
|
|
|
289
290
|
@property
|
|
290
|
-
def handle(self):
|
|
291
|
+
def handle(self) -> Optional[HANDLE]:
|
|
291
292
|
"""SimConnect 句柄(HANDLE),未连接时为 None"""
|
|
292
293
|
return self._hSimConnect
|
|
293
294
|
|
|
294
295
|
@property
|
|
295
|
-
def dll(self):
|
|
296
|
+
def dll(self) -> Optional[WinDLL]:
|
|
296
297
|
"""已加载的 WinDLL 对象,未加载时为 None"""
|
|
297
298
|
return self._dll
|
|
298
299
|
|
|
299
300
|
@property
|
|
300
|
-
def is_open(self):
|
|
301
|
+
def is_open(self) -> bool:
|
|
301
302
|
"""是否已成功打开连接"""
|
|
302
303
|
return (self._hSimConnect is not None
|
|
303
304
|
and self._hSimConnect.value is not None
|
|
304
305
|
and self._hSimConnect.value != 0)
|
|
305
306
|
|
|
306
|
-
def __repr__(self):
|
|
307
|
+
def __repr__(self) -> str:
|
|
307
308
|
status = "已连接" if self.is_open else "未连接"
|
|
308
309
|
dll_status = "已加载" if self._dll else "未加载"
|
|
309
310
|
return f"<SimConnect {status}, DLL {dll_status}>"
|
|
310
311
|
|
|
311
|
-
def __enter__(self):
|
|
312
|
+
def __enter__(self) -> 'SimConnect':
|
|
312
313
|
"""支持 with 语句 — 返回自身"""
|
|
313
314
|
return self
|
|
314
315
|
|
|
315
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
316
|
+
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
316
317
|
"""退出 with 块时自动关闭连接"""
|
|
317
318
|
self.close()
|
|
318
319
|
|
|
319
320
|
# ── 初始化 ────────────────────────────────────
|
|
320
321
|
|
|
321
|
-
def load_dll(self, dll_path=None):
|
|
322
|
+
def load_dll(self, dll_path: Optional[str] = None) -> None:
|
|
322
323
|
"""加载 SimConnect.dll。
|
|
323
324
|
|
|
324
325
|
Args:
|
|
@@ -364,7 +365,10 @@ class SimConnect:
|
|
|
364
365
|
d.SimConnect_Close.argtypes = [HANDLE]
|
|
365
366
|
|
|
366
367
|
# SimConnect_CallDispatch
|
|
367
|
-
|
|
368
|
+
# 第一个参数必须是 POINTER(SIMCONNECT_RECV),c_void_p 会导致 .contents.dwID 失败
|
|
369
|
+
self._DispatchProc = ctypes.WINFUNCTYPE(
|
|
370
|
+
None, POINTER(SIMCONNECT_RECV), DWORD, c_void_p,
|
|
371
|
+
)
|
|
368
372
|
d.SimConnect_CallDispatch.restype = HRESULT
|
|
369
373
|
d.SimConnect_CallDispatch.argtypes = [HANDLE, self._DispatchProc, c_void_p]
|
|
370
374
|
|
|
@@ -414,8 +418,9 @@ class SimConnect:
|
|
|
414
418
|
|
|
415
419
|
# ── 连接管理 ──────────────────────────────────
|
|
416
420
|
|
|
417
|
-
def open(self, app_name=b"SimConnectApp", window_handle=None,
|
|
418
|
-
window_event_handle=None,
|
|
421
|
+
def open(self, app_name: bytes = b"SimConnectApp", window_handle: Any = None,
|
|
422
|
+
fifo_size: int = 0, window_event_handle: Any = None,
|
|
423
|
+
config_index: int = 0) -> HANDLE:
|
|
419
424
|
"""建立与 MSFS 的 SimConnect 连接。
|
|
420
425
|
|
|
421
426
|
Args:
|
|
@@ -452,47 +457,50 @@ class SimConnect:
|
|
|
452
457
|
logger.info("SimConnect 已连接 (app=%s)", app_name)
|
|
453
458
|
return hSim
|
|
454
459
|
|
|
455
|
-
def close(self):
|
|
460
|
+
def close(self) -> None:
|
|
456
461
|
"""关闭 SimConnect 连接。"""
|
|
457
462
|
self.stop_background_dispatch()
|
|
458
|
-
|
|
463
|
+
with self._lock:
|
|
464
|
+
hSim = self._hSimConnect
|
|
465
|
+
self._hSimConnect = None
|
|
466
|
+
if self._dll and hSim:
|
|
459
467
|
try:
|
|
460
|
-
self._dll.SimConnect_Close(
|
|
468
|
+
self._dll.SimConnect_Close(hSim)
|
|
461
469
|
logger.info("SimConnect 已断开")
|
|
462
470
|
except Exception as e:
|
|
463
471
|
logger.debug("SimConnect_Close 异常: %s", e)
|
|
464
|
-
self._hSimConnect = None
|
|
465
472
|
|
|
466
473
|
# ── dispatch ──────────────────────────────────
|
|
467
474
|
|
|
468
|
-
def call_dispatch(self, callback):
|
|
475
|
+
def call_dispatch(self, callback: Callable) -> None:
|
|
469
476
|
"""设置并调用 dispatch 回调处理 SimConnect 消息。
|
|
470
477
|
|
|
471
478
|
Args:
|
|
472
479
|
callback: 回调函数,签名 (pData, cbData, pContext) -> None。
|
|
473
|
-
其中 pData 是
|
|
480
|
+
其中 pData 是 POINTER(SIMCONNECT_RECV),可直接访问 .contents.dwID。
|
|
474
481
|
"""
|
|
475
|
-
if not self._dll
|
|
482
|
+
if not self._dll:
|
|
476
483
|
return
|
|
477
484
|
with self._lock:
|
|
478
485
|
self._dispatch_cb = self._DispatchProc(callback)
|
|
479
|
-
|
|
480
|
-
self._hSimConnect
|
|
481
|
-
|
|
486
|
+
cb = self._dispatch_cb
|
|
487
|
+
hSim = self._hSimConnect
|
|
488
|
+
if not hSim or not hSim.value:
|
|
489
|
+
return
|
|
490
|
+
self._dll.SimConnect_CallDispatch(hSim, cb, None)
|
|
482
491
|
|
|
483
|
-
def dispatch(self):
|
|
492
|
+
def dispatch(self) -> None:
|
|
484
493
|
"""处理一次 SimConnect 消息队列。需要先通过 set_dispatch_cb() 设置回调。"""
|
|
485
|
-
if not self._dll
|
|
494
|
+
if not self._dll:
|
|
486
495
|
return
|
|
487
496
|
with self._lock:
|
|
488
497
|
cb = self._dispatch_cb
|
|
489
|
-
|
|
498
|
+
hSim = self._hSimConnect
|
|
499
|
+
if not cb or not hSim or not hSim.value:
|
|
490
500
|
return
|
|
491
|
-
self._dll.SimConnect_CallDispatch(
|
|
492
|
-
self._hSimConnect, cb, None
|
|
493
|
-
)
|
|
501
|
+
self._dll.SimConnect_CallDispatch(hSim, cb, None)
|
|
494
502
|
|
|
495
|
-
def set_dispatch_cb(self, callback):
|
|
503
|
+
def set_dispatch_cb(self, callback: Callable) -> None:
|
|
496
504
|
"""设置 dispatch 回调函数(不触发调用)。
|
|
497
505
|
|
|
498
506
|
Args:
|
|
@@ -503,7 +511,7 @@ class SimConnect:
|
|
|
503
511
|
|
|
504
512
|
# ── 后台 dispatch 线程 ────────────────────────
|
|
505
513
|
|
|
506
|
-
def start_background_dispatch(self, callback=None):
|
|
514
|
+
def start_background_dispatch(self, callback: Optional[Callable] = None) -> None:
|
|
507
515
|
"""启动后台线程持续 dispatch(适合高频率数据接收场景)。
|
|
508
516
|
|
|
509
517
|
Args:
|
|
@@ -526,7 +534,7 @@ class SimConnect:
|
|
|
526
534
|
self._dispatch_thread.start()
|
|
527
535
|
logger.debug("后台 dispatch 线程已启动")
|
|
528
536
|
|
|
529
|
-
def stop_background_dispatch(self):
|
|
537
|
+
def stop_background_dispatch(self) -> None:
|
|
530
538
|
"""停止后台 dispatch 线程。"""
|
|
531
539
|
self._dispatch_running = False
|
|
532
540
|
self._dispatch_stop_event.set() # 立即唤醒 dispatch 循环
|
|
@@ -562,8 +570,9 @@ class SimConnect:
|
|
|
562
570
|
|
|
563
571
|
# ── 数据定义 ──────────────────────────────────
|
|
564
572
|
|
|
565
|
-
def add_to_data_definition(self, define_id, simvar_name, unit,
|
|
566
|
-
datatype=0, epsilon=0.0,
|
|
573
|
+
def add_to_data_definition(self, define_id: int, simvar_name: bytes, unit: bytes,
|
|
574
|
+
datatype: int = 0, epsilon: float = 0.0,
|
|
575
|
+
datasize: int = 0xFFFFFFFF) -> int:
|
|
567
576
|
"""注册 SimVar 数据定义。
|
|
568
577
|
|
|
569
578
|
Args:
|
|
@@ -582,7 +591,7 @@ class SimConnect:
|
|
|
582
591
|
c_ulong(datatype), c_float(epsilon), DWORD(datasize),
|
|
583
592
|
)
|
|
584
593
|
|
|
585
|
-
def clear_data_definition(self, define_id):
|
|
594
|
+
def clear_data_definition(self, define_id: int) -> int:
|
|
586
595
|
"""清除数据定义。"""
|
|
587
596
|
return self._dll.SimConnect_ClearDataDefinition(
|
|
588
597
|
self._hSimConnect, DWORD(define_id)
|
|
@@ -590,8 +599,9 @@ class SimConnect:
|
|
|
590
599
|
|
|
591
600
|
# ── 数据请求 ──────────────────────────────────
|
|
592
601
|
|
|
593
|
-
def request_data_on_simobject_type(self, request_id, define_id,
|
|
594
|
-
object_id=0,
|
|
602
|
+
def request_data_on_simobject_type(self, request_id: int, define_id: int,
|
|
603
|
+
object_id: int = 0,
|
|
604
|
+
simobject_type: int = 0) -> int:
|
|
595
605
|
"""请求指定类型的 SimObject 数据。
|
|
596
606
|
|
|
597
607
|
Args:
|
|
@@ -605,8 +615,10 @@ class SimConnect:
|
|
|
605
615
|
DWORD(object_id), c_ulong(simobject_type),
|
|
606
616
|
)
|
|
607
617
|
|
|
608
|
-
def request_data_on_simobject(self, request_id, define_id
|
|
609
|
-
|
|
618
|
+
def request_data_on_simobject(self, request_id: int, define_id: int,
|
|
619
|
+
object_id: int = 0, period: int = 4,
|
|
620
|
+
flags: int = 0, origin: int = 0,
|
|
621
|
+
interval: int = 0, limit: int = 0) -> int:
|
|
610
622
|
"""请求指定 SimObject 的持续数据更新(更常用的 API)。
|
|
611
623
|
|
|
612
624
|
Args:
|
|
@@ -625,8 +637,9 @@ class SimConnect:
|
|
|
625
637
|
DWORD(origin), DWORD(interval), DWORD(limit),
|
|
626
638
|
)
|
|
627
639
|
|
|
628
|
-
def add_and_request(self, request_id, define_id
|
|
629
|
-
|
|
640
|
+
def add_and_request(self, request_id: int, define_id: int,
|
|
641
|
+
simvar_name: bytes, unit: bytes,
|
|
642
|
+
datatype: int = 0, period: int = 4) -> int:
|
|
630
643
|
"""注册定义并立即发起持续请求(一次性完成两个步骤)。
|
|
631
644
|
|
|
632
645
|
Args:
|
|
@@ -644,8 +657,10 @@ class SimConnect:
|
|
|
644
657
|
|
|
645
658
|
# ── 数据写入 ──────────────────────────────────
|
|
646
659
|
|
|
647
|
-
def set_data_on_simobject(self, define_id, object_id=0,
|
|
648
|
-
flags=0, array_count=1,
|
|
660
|
+
def set_data_on_simobject(self, define_id: int, object_id: int = 0,
|
|
661
|
+
flags: int = 0, array_count: int = 1,
|
|
662
|
+
unit_size: int = 8,
|
|
663
|
+
data_ptr: Optional[c_void_p] = None) -> Optional[int]:
|
|
649
664
|
"""向 SimObject 写入数据。
|
|
650
665
|
|
|
651
666
|
Args:
|
|
@@ -657,13 +672,13 @@ class SimConnect:
|
|
|
657
672
|
data_ptr: 数据指针(c_void_p),为 None 时跳过。
|
|
658
673
|
"""
|
|
659
674
|
if data_ptr is None:
|
|
660
|
-
return
|
|
675
|
+
return None
|
|
661
676
|
return self._dll.SimConnect_SetDataOnSimObject(
|
|
662
677
|
self._hSimConnect, DWORD(define_id), c_ulong(object_id),
|
|
663
678
|
DWORD(flags), DWORD(array_count), DWORD(unit_size), data_ptr,
|
|
664
679
|
)
|
|
665
680
|
|
|
666
|
-
def write_double(self, define_id, value):
|
|
681
|
+
def write_double(self, define_id: int, value: float) -> Optional[int]:
|
|
667
682
|
"""快捷方法:写入一个 double 值。
|
|
668
683
|
|
|
669
684
|
Args:
|
|
@@ -676,7 +691,7 @@ class SimConnect:
|
|
|
676
691
|
)
|
|
677
692
|
|
|
678
693
|
@staticmethod
|
|
679
|
-
def event_data_float(value):
|
|
694
|
+
def event_data_float(value: float) -> int:
|
|
680
695
|
"""将 float 转换为 DWORD 位表示(用于需要浮点参数的事件)。
|
|
681
696
|
|
|
682
697
|
某些 SimConnect 事件(如襟翼角度)需要将 float 的二进制表示
|
|
@@ -689,7 +704,7 @@ class SimConnect:
|
|
|
689
704
|
|
|
690
705
|
# ── 事件 ──────────────────────────────────────
|
|
691
706
|
|
|
692
|
-
def map_client_event_to_sim_event(self, event_id, event_name):
|
|
707
|
+
def map_client_event_to_sim_event(self, event_id: int, event_name: bytes) -> int:
|
|
693
708
|
"""将客户端事件 ID 映射到 Sim 事件名称。
|
|
694
709
|
|
|
695
710
|
Args:
|
|
@@ -700,8 +715,9 @@ class SimConnect:
|
|
|
700
715
|
self._hSimConnect, DWORD(event_id), event_name,
|
|
701
716
|
)
|
|
702
717
|
|
|
703
|
-
def transmit_client_event(self, object_id=0, event_id=
|
|
704
|
-
group_priority=0x19000000,
|
|
718
|
+
def transmit_client_event(self, object_id: int = 0, event_id: int = 0,
|
|
719
|
+
data: int = 0, group_priority: int = 0x19000000,
|
|
720
|
+
flags: int = 16) -> int:
|
|
705
721
|
"""发送客户端事件到 SimObject。
|
|
706
722
|
|
|
707
723
|
Args:
|
|
@@ -718,7 +734,7 @@ class SimConnect:
|
|
|
718
734
|
|
|
719
735
|
# ── 系统事件 ──────────────────────────────────
|
|
720
736
|
|
|
721
|
-
def subscribe_to_system_event(self, event_id, event_name):
|
|
737
|
+
def subscribe_to_system_event(self, event_id: int, event_name: bytes) -> int:
|
|
722
738
|
"""订阅系统事件。
|
|
723
739
|
|
|
724
740
|
Args:
|
|
@@ -731,7 +747,7 @@ class SimConnect:
|
|
|
731
747
|
|
|
732
748
|
# ── 工具 ──────────────────────────────────────
|
|
733
749
|
|
|
734
|
-
def get_last_sent_packet_id(self):
|
|
750
|
+
def get_last_sent_packet_id(self) -> int:
|
|
735
751
|
"""获取最后发送的数据包 ID。"""
|
|
736
752
|
pid = DWORD(0)
|
|
737
753
|
self._dll.SimConnect_GetLastSentPacketID(
|
|
@@ -739,13 +755,13 @@ class SimConnect:
|
|
|
739
755
|
)
|
|
740
756
|
return pid.value
|
|
741
757
|
|
|
742
|
-
def read_double(self, pData):
|
|
758
|
+
def read_double(self, pData: Any) -> Tuple[Optional[int], Optional[float]]:
|
|
743
759
|
"""从 dispatch 回调的 pData 中读取 double 值。
|
|
744
760
|
|
|
745
761
|
用于 SIMCONNECT_RECV_ID_SIMOBJECT_DATA / _BYTYPE 消息。
|
|
746
762
|
|
|
747
763
|
Args:
|
|
748
|
-
pData:
|
|
764
|
+
pData: POINTER(SIMCONNECT_RECV),dispatch 回调的第一个参数。
|
|
749
765
|
|
|
750
766
|
Returns:
|
|
751
767
|
(request_id, float_value) 元组,解析失败返回 (None, None)。
|
|
@@ -759,13 +775,13 @@ class SimConnect:
|
|
|
759
775
|
return None, None
|
|
760
776
|
|
|
761
777
|
@staticmethod
|
|
762
|
-
def read_data(pData, datatype=0):
|
|
778
|
+
def read_data(pData: Any, datatype: int = 0) -> Any:
|
|
763
779
|
"""从 dispatch 回调指针中按类型读取数据值。
|
|
764
780
|
|
|
765
781
|
用于 dispatch 回调中解析不同类型的数据。
|
|
766
782
|
|
|
767
783
|
Args:
|
|
768
|
-
pData:
|
|
784
|
+
pData: POINTER(SIMCONNECT_RECV),dispatch 回调的第一个参数。
|
|
769
785
|
datatype: SIMCONNECT_DATATYPE_*,默认 0(FLOAT64)。
|
|
770
786
|
|
|
771
787
|
Returns:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|