semvec/pypi-packages huggingface dataset:
tkmap 0.1.2
A simple tkinter map widget
License: Apache-2.0
Requires Python: >=3.10

# tkmap

A Tkinter-based interactive map widget for Python, supporting OpenStreetMap and custom tile sources. Easily embed a map in your Tkinter GUI, handle user interaction, and respond to map events.

## Features
- Fast, smooth map panning and zooming
- Customizable tile sources (e.g., OpenStreetMap)
- Mouse and viewport event handling
- Simple integration with Tkinter applications

## Installation
Install via pip (after cloning or when available on PyPI):

```sh
pip install tkmap
```

## Minimal Example
This example launches a Tkinter window with an interactive OpenStreetMap viewer:

```python
import tkinter as tk
from pathlib import Path
import requests
from platformdirs import user_cache_dir
from tkmap import LonLat, MapWidget
from tkmap.tileloaders.default import DefaultTileLoader

def main():
    tile_loader = DefaultTileLoader(
        url="https://tile.openstreetmap.org/{z}/{x}/{y}.png",
        base_cache_dir=Path(user_cache_dir("tkmap")) / "tile_cache",
        requests_session=requests.Session(),
    )
    root = tk.Tk()
    root.geometry("800x600")
    root.title("tkmap OpenStreetMap Demo")
    map_widget = MapWidget(
        root,
        center=LonLat(0, 0),
        zoom=2,
        tile_loader=tile_loader,
    )
    map_widget.pack(fill="both", expand=True)
    tile_loader.start_remote_fetch_queue_processing(root.winfo_toplevel(), interval_ms=100)
    root.mainloop()

if __name__ == "__main__":
    main()
```

## Handling Events
You can respond to mouse movement and viewport changes using event callbacks:

```python
from tkmap.events import MouseMovedEvent, ViewportChangeEvent

# ... (setup code as above)

def on_mouse_moved(event: MouseMovedEvent):
    print(f"Mouse at lat={event.lonlat.lat:.6f}, lon={event.lonlat.lon:.6f}")

def on_viewport_changed(event: ViewportChangeEvent):
    print(f"Viewport center: {event.center.lat:.6f}, {event.center.lon:.6f}, zoom={event.zoom}")

map_widget.on_mouse_moved(on_mouse_moved)
map_widget.on_viewport_change(on_viewport_changed)
```

## License
Apache-2.0
altruistclient 0.1.1
Async library for discovering and fetching data from Altruist sensors
License: Apache-2.0
Requires Python: <4.0,>=3.9

# AltruistClient

Python async library for discovering and communicating with Altruist ESP32-based sensors over the local network using mDNS (zeroconf) and HTTP.

## Features

- Discover sensors on your LAN using Zeroconf (`_altruist._tcp.local.`)
- Fetch sensor metadata and measurement data from `/data.json`
- Filter supported sensor names
- Async/AIOHTTP-based for fast, non-blocking usage

---

## Installation

```bash
pip install atruistclient
```

---

## Quick Start

```python
import asyncio
from aiohttp import ClientSession
from zeroconf.asyncio import AsyncZeroconf
from altruistclient import AltruistDiscoverer, AltruistClient

async def main():
    async with AsyncZeroconf() as zc, ClientSession() as session:
        discoverer = AltruistDiscoverer(zc, session)
        devices = await discoverer.get_devices()

        for device in devices:
            client = AltruistClient(session, device)
            data = await client.fetch_data()
            print(f"Device {client.device_id} (fw: {client.fw_version})")
            print("Sensor names:", client.sensor_names)
            print("Data:", data)

asyncio.run(main())
```

---

## Class Overview

### `AltruistDiscoverer`

- Scans for `_altruist._tcp.local.` devices using zeroconf.
- Filters and validates devices via their `/data.json` response.
- Returns a list of `AltruistDeviceModel` instances.

```python
discoverer = AltruistDiscoverer(zc, session)
devices = await discoverer.get_devices()
```

---

### `AltruistClient`

- Handles data fetching and parsing from a specific device.
- Extracts firmware version, sensor types, and measurements.

```python
client = AltruistClient(session, device)
data = await client.fetch_data()
print(client.fw_version, client.sensor_names)
```

You can also construct it directly from an IP:

```python
client = await AltruistClient.from_ip_address(session, "192.168.1.45")
```

---

### `AltruistDeviceModel`

Simple dataclass containing:

- `id`: sensor ID (from `/data.json`)
- `ip_address`: resolved IP
- `fw_version`: firmware version (optional)

```python
@dataclass
class AltruistDeviceModel:
    id: str
    ip_address: str
    name: str = "Altruist Sensor"
    fw_version: str | None = None
```

---

## Notes

- `get_devices()` waits 5 seconds for mDNS discovery.
- Only devices that respond to `/data.json` and provide a valid `sensor_id` are returned.
- Internally uses `aiohttp`.