WIP
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
|
warehouse_*/
|
||||||
*.swo
|
*.swo
|
||||||
*.swp
|
*.swp
|
||||||
*.json
|
*.json
|
||||||
40
README.md
40
README.md
@@ -1,5 +1,6 @@
|
|||||||
# 2026-linux-skladman
|
# 2026-linux-skladman
|
||||||
|
|
||||||
|
|
||||||
## Что это
|
## Что это
|
||||||
|
|
||||||
`2026-linux-skladman` - это ИИ-сервис для учёта вещей на складе. Он позволяет:
|
`2026-linux-skladman` - это ИИ-сервис для учёта вещей на складе. Он позволяет:
|
||||||
@@ -14,4 +15,41 @@
|
|||||||
коробки" предоставляается привязка к Telegram.
|
коробки" предоставляается привязка к Telegram.
|
||||||
|
|
||||||
Учтено то, что может возникнуть необходимость работы как с self-hosted LLM, так
|
Учтено то, что может возникнуть необходимость работы как с self-hosted LLM, так
|
||||||
и с крупными ИИ-сервисами (Gemini, OpenAI и т.д.).
|
и с крупными ИИ-сервисами (Gemini, OpenAI и т.д.).
|
||||||
|
|
||||||
|
|
||||||
|
## Пример взаимодействия
|
||||||
|
|
||||||
|
#### Найти что-то и взять сколько-нибудь
|
||||||
|
```
|
||||||
|
USER: Мне надо из 12 вольт сделать 5 вольт
|
||||||
|
SYSTEM: В "Y12" лежат buck DCDC преобразователи, 5 штук
|
||||||
|
USER: Взял 2
|
||||||
|
SYSTEM: Записал, что их осталось 3 штуки
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Узнать, что лежит в ячейке, и исправить данные
|
||||||
|
```
|
||||||
|
USER: че в s3
|
||||||
|
SYSTEM: В "S3" лежат 12 штук Arduino
|
||||||
|
USER: уже нет, они переехали в p4
|
||||||
|
SYSTEM: Записал, что теперь в "S3" пусто, а в "P4" лежит 12 штук Arduino.
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Реорганизация склада
|
||||||
|
```
|
||||||
|
USER: Мы объединили S3 и S4, теперь оно называется Q2
|
||||||
|
SYSTEM: Записал, что больше ячеек S3 и S4 не существуют, но теперь есть
|
||||||
|
ячейка Q2, в которой лежат Arduino (12 штук) и ESP32 (5 штук).
|
||||||
|
USER: И ещё ардуин осталось 8, а есп кончились
|
||||||
|
SYSTEM: Записал, что теперь в Q2 лежат 8 штук Arduino
|
||||||
|
```
|
||||||
|
|
||||||
|
#### И так далее
|
||||||
|
|
||||||
|
|
||||||
|
## Структура файлов
|
||||||
|
|
||||||
|
* `main.py` - скрипт, который нужно запускать
|
||||||
|
* `config.json` - конфигурация сервиса, генерируется автоматически при первом запуске
|
||||||
|
* `warehouse_<NAME>/` - папка с данными склада, не редактируйте файлы оттуда вручную
|
||||||
89
warehouse.py
Normal file
89
warehouse.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
""" Warehouse API """
|
||||||
|
|
||||||
|
import os
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dataclasses
|
||||||
|
#
|
||||||
|
@dataclass
|
||||||
|
class WarehouseLocation:
|
||||||
|
""" Location inside warehouse """
|
||||||
|
# human readable name of location within warehouse
|
||||||
|
name: str
|
||||||
|
# description on how to find the location
|
||||||
|
how_to_find: str = 'Somewhere inside the warehouse'
|
||||||
|
# remarks
|
||||||
|
remarks: str = ''
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class WarehouseItem:
|
||||||
|
""" Item stored within warehouse """
|
||||||
|
# human readable name of item
|
||||||
|
name: str
|
||||||
|
# human readable name of measurement unit
|
||||||
|
unit: str = 'units'
|
||||||
|
# count of item in units
|
||||||
|
count: int = 1
|
||||||
|
# remarks
|
||||||
|
remarks: str = ''
|
||||||
|
# location ID where the item is stored
|
||||||
|
location_id: int = 0
|
||||||
|
|
||||||
|
#
|
||||||
|
# Private
|
||||||
|
#
|
||||||
|
_warehouse_name = None
|
||||||
|
_warehouse_path = None
|
||||||
|
_locations = {}
|
||||||
|
_entries = {}
|
||||||
|
|
||||||
|
async def _read_file(path: str) -> str:
|
||||||
|
""" Read file content and strip it.
|
||||||
|
Empty string on error.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
return f.read().strip()
|
||||||
|
except:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
async def _write_file(path: str, content: str) -> bool:
|
||||||
|
""" Write file content. """
|
||||||
|
try:
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
f.write(content)
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def _fsck_warehouse(path: str) -> bool:
|
||||||
|
""" Check warehouse for errors and fix them if possible.
|
||||||
|
Returns True if warehouse is usable.
|
||||||
|
"""
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def _create_warehouse(path: str) -> bool:
|
||||||
|
""" Create warehouse.
|
||||||
|
Returns True if warehouse is usable.
|
||||||
|
"""
|
||||||
|
if os.path.isdir(path):
|
||||||
|
return await _fsck_warehouse(path)
|
||||||
|
locations[0] = WarehouseLocation(
|
||||||
|
name='Unsorted',
|
||||||
|
how_to_find='',
|
||||||
|
remarks='Pseudolocation for unsorted items'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Public
|
||||||
|
#
|
||||||
|
async def init(name: str) -> bool:
|
||||||
|
""" Initialize warehouse API. """
|
||||||
|
global _warehouse_name, _warehouse_path
|
||||||
|
_warehouse_name = name
|
||||||
|
_warehouse_path = f'warehouse_{name}'
|
||||||
|
return await _create_warehouse(_warehouse_path)
|
||||||
Reference in New Issue
Block a user