<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>timsa.ru: заметки с тегом python</title>
<link>https://timsa.ru/tags/python/</link>
<description>Моя записная книжка. Комментарии отключены из-за спама. Для вопросов используйте эту страничку</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.0 (v4079)</generator>

<itunes:subtitle>Моя записная книжка. Комментарии отключены из-за спама. Для вопросов используйте эту страничку</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>Beacon</title>
<guid isPermaLink="false">232</guid>
<link>https://timsa.ru/all/beacon/</link>
<pubDate>Fri, 06 Jun 2025 17:26:15 +0500</pubDate>
<author></author>
<comments>https://timsa.ru/all/beacon/</comments>
<description>
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;import uasyncio as asyncio
from machine import Pin,ADC,PWM,UART
import utime
import math

uart = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
#uart = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart.init(bits=8, parity=None, stop=1)

async def readuart():
    while True:
        if uart.any():
            data = uart.read()
            print(data)
        await asyncio.sleep_ms(1000)

async def heartbeat():
    temp_sensor = ADC(4)
    while True:
        current_time = utime.localtime()
        hours = current_time[3]
        minutes = current_time[4]
        seconds = current_time[5]
        temp = 27 - (temp_sensor.read_u16() * 3.3 / (65535) - 0.706)/0.001721
        #print(&amp;quot;{:02d}:{:02d}:{:02d} t={:3.1f}&amp;quot;.format(hours, minutes, seconds, temp))
        uart.write(&amp;quot;{:02d}:{:02d}:{:02d} t={:3.1f}&amp;quot;.format(hours, minutes, seconds, temp))
        await asyncio.sleep_ms(60000)

async def ledlight():
    #led = Pin(25, Pin.OUT)
    led = PWM(Pin(25, Pin.OUT))
    led.freq(2048)
    
    start_value = 1
    end_value = 65535
    num_values = 100
    growth_factor = (end_value / start_value) ** (1 / (num_values - 1))
    decay_factor = (start_value / end_value) ** (1 / (num_values - 1))
    
    while True:
        for i in range(num_values):
            value = start_value * (growth_factor ** i)
            led.duty_u16(int(value))
            await asyncio.sleep_ms(int(500/num_values))
            
        for i in range(num_values):
            value = end_value * (decay_factor ** i)
            led.duty_u16(int(value))
            await asyncio.sleep_ms(int(500/num_values))
            
async def main():
    loop  =  asyncio.get_event_loop ()
    loop.create_task(heartbeat())
    loop.create_task(ledlight())
    loop.create_task(readuart())
    loop.run_forever ()

if __name__ == '__main__':
    asyncio.run(main())&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>Waveshare SX1262 LoRa + Raspberry Pi Pico</title>
<guid isPermaLink="false">228</guid>
<link>https://timsa.ru/all/waveshare-sx1262-lora-raspberry-pi-pico/</link>
<pubDate>Tue, 06 May 2025 08:24:56 +0500</pubDate>
<author></author>
<comments>https://timsa.ru/all/waveshare-sx1262-lora-raspberry-pi-pico/</comments>
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://timsa.ru/pictures/image-1.png" width="960" height="698" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://timsa.ru/pictures/image-2.png" width="960" height="530" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://timsa.ru/pictures/image-3.png" width="960" height="291" alt="" /&gt;
&lt;/div&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Raspberry Pi Pico header&lt;/li&gt;
&lt;li&gt;Status indicators&lt;br /&gt;
PWR: power indicator&lt;br /&gt;
CHG: recharge indicator&lt;/li&gt;
&lt;li&gt;RF switch control&lt;br /&gt;
A: controlled by high level&lt;br /&gt;
B: controlled by GPIO22&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;MCP73831 recharge IC&lt;br /&gt;
SX1262 module&lt;br /&gt;
IPEX 1 antenna connector&lt;br /&gt;
PH1.25 battery header&lt;/p&gt;
&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/77668385/waveshare-sx1262-lorawan-hat"&gt;https://stackoverflow.com/questions/77668385/waveshare-sx1262-lorawan-hat&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/maximecongi/LoRaRF-Python-custom"&gt;https://github.com/maximecongi/LoRaRF-Python-custom&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/chandrawi/LoRaRF-Python/tree/main/examples/SX126x"&gt;https://github.com/chandrawi/LoRaRF-Python/tree/main/examples/SX126x&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/ehong-tl/micropySX126X/tree/master/example"&gt;https://github.com/ehong-tl/micropySX126X/tree/master/example&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://microkontroller.ru/raspberry-pi-projects/podklyuchenie-modulya-lora-k-raspberry-pi-i-odnorangovaya-set-s-arduino/"&gt;https://microkontroller.ru/raspberry-pi-projects/podklyuchenie-modulya-lora-k-raspberry-pi-i-odnorangovaya-set-s-arduino/&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://wiki.openelab.io/raspbeery-pi/waveshare-sx1262-lora-hat-for-raspberry-uart"&gt;https://wiki.openelab.io/raspbeery-pi/waveshare-sx1262-lora-hat-for-raspberry-uart&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>Отгадыватель кроссвордов</title>
<guid isPermaLink="false">107</guid>
<link>https://timsa.ru/all/wow/</link>
<pubDate>Tue, 21 Jul 2020 13:44:14 +0500</pubDate>
<author></author>
<comments>https://timsa.ru/all/wow/</comments>
<description>
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#!/usr/bin/env python3

import sys
from itertools import permutations
import re
import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import os.path

if len(sys.argv) &amp;lt; 4:
  print(&amp;quot;Usage: \nwords.py yandex|google|filename|none алфавит маска\n&amp;quot;)
  sys.exit()

search  = sys.argv[1]
alphabet = sys.argv[2]
pattern = sys.argv[3]

yandex = 'https://yandex.ru/search/?noreask=1&amp;amp;text='
google = 'https://www.google.ru/search?ie=UTF-8&amp;amp;hl=ru&amp;amp;spell=0&amp;amp;nfpr=1&amp;amp;q='

ua = UserAgent()
myheaders = {'User-Agent': str(ua.random), 'referer': 'https://www.google.ru'}

# все варианты перестановок
allwords = permutations(alphabet, len(pattern))

# выкидываем дубликаты
words = list(set(allwords))

# склеиваем 2-мерный список в одномерный
words2 = []
for word in words:
  str = ''.join(word)
  words2.append(str)

# проходим регекспом
obj = re.compile(pattern)
words = list(filter(lambda str: obj.search(str), words2))

print('Всего вариантов %d' % len(words))

output = []
wordlist = []

if os.path.exists(search):
  f = open(search, 'r', encoding = 'utf-8')
  wordlist = [line.strip() for line in f]
  f.close()
  print('Размер словаря %d' % len(wordlist))

for word in words:
  if search == 'google':
    r = requests.get(google + word, headers=myheaders)
    r.encoding = 'utf-8'
    soup = BeautifulSoup(r.text, 'html5lib')
    stat = soup.find('div', id='resultStats')
    if stat is not None:
      qty = re.search('Результатов:\sпримерно\s(.*)\s\(\d+,\d+\sсек.\)', stat.text)
      x = qty.group(1)
      x = x.split()
      x = ''.join(x)
      output.append([word, int(x)])
      print(&amp;quot;%s - %s&amp;quot; % (word, x))
    else:
      output.append([word, 0])

  elif search == 'yandex':
    r = requests.get(yandex + word, headers=myheaders)
    r.encoding = 'utf-8'
    soup = BeautifulSoup(r.text, 'html5lib')
    stat = soup.find('div', {'class': 'serp-adv__found'})
    if stat is not None:
      qty = re.search('Нашлось\s(.*)\sрезультатов', stat.text)
      x = qty.group(1)
      output.append([word, x])
      print(&amp;quot;%s - %s&amp;quot; % (word, x))
    else:
      output.append([word, 0])
      
  elif os.path.exists(search):
    if word in wordlist:
      output.append([word, 0])
    
  else:
    output.append([word, 0])

print('Отфильтрованно с помощью %s' % search)

output.sort(key=lambda x: x[1], reverse=True)

for str in output:
  print(str[0])&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>Подключаем Dadget CO2 к серваку</title>
<guid isPermaLink="false">116</guid>
<link>https://timsa.ru/all/podklyuchaem-dadget-co2-k-servaku/</link>
<pubDate>Mon, 20 Jul 2020 22:38:42 +0500</pubDate>
<author></author>
<comments>https://timsa.ru/all/podklyuchaem-dadget-co2-k-servaku/</comments>
<description>
&lt;ol start="1"&gt;
&lt;li&gt;Сначала сделаем чтобы любой пользователь мог обращаться к устройству&lt;br /&gt;
создаем /etc/udev/rules.d/10-co2mon.rules&lt;br /&gt;
с содержимым&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;ACTION==&amp;quot;add|change&amp;quot;, SUBSYSTEMS==&amp;quot;usb&amp;quot;, ATTRS{idVendor}==&amp;quot;04d9&amp;quot;, ATTRS{idProduct}==&amp;quot;a052&amp;quot;, MODE:=&amp;quot;0666&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;щелкаем&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;udevadm control --reload
udevadm trigger&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;проверяем что /dev/usb/hiddev0 теперь crw-rw-rw-&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Подключаем библиотечку &lt;s&gt;PyUSB&lt;/s&gt; hid. PyUSB глючное говно вызывающее странные эффекты, например пропадение устройства hiddev0.&lt;br /&gt;
pip3 install hid (или hidapi уже не помню, это гуглится)&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;Читаем (алгоритм расшифровки передрал с сишного проекта co2mod)&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#!/usr/bin/env python3

import hid
import time

def decode_co(data):
    # кручу-верчу
    data[0], data[2] = data[2], data[0]
    data[1], data[4] = data[4], data[1]
    data[3], data[7] = data[7], data[3]
    data[5], data[6] = data[6], data[5]
    
    result = bytearray(8)

    # всех обмануть хочу
    result[7] = ((data[6] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[7] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    result[6] = ((data[5] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[6] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    result[5] = ((data[4] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[5] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    result[4] = ((data[3] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[4] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    result[3] = ((data[2] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[3] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    result[2] = ((data[1] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[2] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    result[1] = ((data[0] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[1] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    result[0] = ((data[7] &amp;lt;&amp;lt; 5) &amp;amp; 0xFF) | ((data[0] &amp;gt;&amp;gt; 3) &amp;amp; 0xFF)
    
    magic_word = b'Htemp99e'
    for i in range(8):
        r = ((magic_word[i] &amp;lt;&amp;lt; 4) &amp;amp; 0xFF) | ((magic_word[i] &amp;gt;&amp;gt; 4) &amp;amp; 0xFF)
        if result[i] &amp;lt; r:
            result[i] = 0xFF - r + result[i]
        else:
            result[i] = result[i] - r

    # не знаю почему, но у меня проверка чек-суммы никогда не сходилась    
    #if result[0]+result[1]+result[2] != result[3]:
    #    return 0

    res = (result[1] &amp;lt;&amp;lt; 8) + result[2]

    if result[0] == 0x42:
        print(&amp;quot;T={0}&amp;quot;.format(res * 0.0625 - 273.15))
        return 1
    elif result[0] == 0x50:
        print(&amp;quot;CO={0}&amp;quot;.format(res))
        return 2
    return 0
    
try:
    h = hid.device()
    h.open(0x04d9, 0xa052)

    # хз, не вникал
    h.set_nonblocking(1)

    # по идее это отправка некой magic_table которой шифруется ответ, но и без любой из этих строк работает
    #h.write(b'8\x00\x00\x00\x00\x00\x00\x00\x00')
    h.send_feature_report([0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
    time.sleep(0.05)

    co = 1
    t = 1
    while co | t:
        d = h.read(8)
        if d:
            n = decode_co(d)
            if n == 1:
                t = 0
            elif n == 2:
                co = 0

    h.close()

except IOError as ex:
    print(ex)&lt;/code&gt;&lt;/pre&gt;</description>
</item>


</channel>
</rss>