вівторок, 27 грудня 2016 р.

Загрузить BLOB в TImage Delphi

Есть у меня простая табличка в ORACLE, в которой есть 2 поля: ИД и BLOB (картинка в PNG). Понадобилось отображать эту картинку на клиенте (Delphi XE3). Погуглив, нашел подходящий вариант, доработал под себя и вот что получилось:
procedure LoadImageFromDbToTImage(img: TImage; Field: string; id: integer);
var
memStream: TMemoryStream;
Graphic: Graphics.TGraphic;
bm: Graphics.Tbitmap;
begin
odsImages.Close;
odsImages.SetVariable('id', id); //ИД картинки
odsImages.Open;
memStream := TMemoryStream.Create;
(odsImages.FieldbyName(Field) as TBlobfield).SaveToStream(memStream);
bm:=Graphics.TBitmap.Create;
Graphic := TPNGGraphic.Create;
{
Для других типов:
bmp - Graphics.TBitmap.Create;
gif - Graphic := TGIFImage.Create;
jpeg - Graphic := TJPEGImage.Create;
}
try
memstream.Seek(0, soFromBeginning);
Graphic.LoadFromStream(memstream);
bm.Assign(Graphic);
img.Picture.Assign(bm);
except
end;
Graphic.Free;
memStream.Free;
bm.Free;
end;
view raw BlobToTImage hosted with ❤ by GitHub



субота, 27 серпня 2016 р.

Raspberry Pi, датчик движения и отправка смс через Twilio

Появилось свободное время, которое я решил потратить на Raspberry Pi. Пару месяцев назад, я уже пробовал фиксировать движение с помощью датчика, подключенного к малине. О проблеме, которая возникла в тот момент я написал в блоге. Сейчас, я решил продолжить развивать эту тему и прикрутить смс оповещение в момент срабатывания датчика. Погуглив, я нашел сайт Twilio, который предоставляет бесплатный вариант отправки смс на верифицированный номер.
Далее я зарегистрировался на сайте, прошел верификацию своего номера, получил триальный номер Twilio и закачал пакет для работы с Twilio:
sudo pip3 install twilio

Также в интернете нашел пример работы с Twilio, который соединил вместе с кодом для работы с датчиком, внес кое-какие свои корректировки и вот что получилось:
import RPi.GPIO as GPIO
import time
from datetime import datetime
def SendSms(msg):
from twilio.rest import TwilioRestClient
client = TwilioRestClient("Your ACCOUNT SID",
"Your AUTH TOKEN")
client.messages.create(to="Your number",
from_="Your Twilio number",
body=msg)
#number of GPIO on board
sensor = 4
GPIO.setmode(GPIO.BCM)
GPIO.setup(sensor, GPIO.IN)
delay_sec = 120
mark_time = 0
cur_state = 0
while True:
time.sleep(1)
cur_state = GPIO.input(sensor)
print(cur_state)
if cur_state == 1:
if time.time() - mark_time > delay_sec:
msg = "Some movement. Time: {0}".format(str(datetime.now())[:-7])
print(msg)
SendSms(msg)
mark_time = time.time()


Смс приходит следующего вида:
Sent from your Twilio trial account
- Some movement. Time: 2016-08-27 16:34:09 

Фото процесса:

понеділок, 22 серпня 2016 р.

Pythonchallenge №10

Продолжаю изучать Python и пробую выполнять задачки с его помощью. На этот раз сайт pythonchallenge.com задание номер 10.
Суть задания заключается в нахождении длины 30-го элемента списка. Также даны начальные элементы последовательности, которую надо продолжить:
a = [1, 11, 21, 1211, 111221, 

Понять алгоритм, по которому строится список мне помог гугл и википедия: https://en.wikipedia.org/wiki/Look-and-say_sequence
В википедии, я обратил внимание на вот этот абзац:
"No digits other than 1, 2, and 3 appear in the sequence..."
и согласно этому ограничению написал свой алгоритм решения этой задачи:
#http://www.pythonchallenge.com/
#challenge num_10
import re
import time
start = time.time()
def GetNextNum(num):
num1 = re.sub('[2]+', ' 0 ', num)
num1 = re.sub('[3]+', ' 0 ', num1)
num2 = re.sub('[1]+', ' 0 ', num)
num2 = re.sub('[3]+', ' 0 ', num2)
num3 = re.sub('[1]+', ' 0 ', num)
num3 = re.sub('[2]+', ' 0 ', num3)
# print(num1)
# print(num2)
# print(num3)
num1 = num1.split()
num2 = num2.split()
num3 = num3.split()
# print(num1)
# print(num2)
# print(num3)
outStr = ''
for iter in range(len(num1)):
if num1[iter] != '0':
curEl = num1[iter]
elif num2[iter] != '0':
curEl = num2[iter]
else: # num3
curEl = num3[iter]
outStr += str(len(curEl)) + curEl[0]
#print(outStr)
return outStr
Mylist = []
curVal = '1'
i = 0
while i <= 30:
i += 1
Mylist.append(curVal)
curVal = GetNextNum(curVal)
print(len(Mylist[30]))
elapsed = (time.time() - start)
print("result returned after {0} seconds." .format(elapsed))
#5808
#result returned after 0.07800412178039551 seconds.


середа, 17 серпня 2016 р.

Projecteuler проблема №5

Недавно начал изучать Python и нашел интересный сайт с задачками, которые пробую решать с помощью Python.
Решил выложить свой вариант решения проблемы №5:
#https://projecteuler.net/problem=5
#python 3.5.2
import time
from functools import reduce as reduce
start = time.time()
simpleList = [2,3,5,7,11,13,17,19]
def DoItSimple(dig):
if dig in simpleList:
outputList.append(dig)
return dig
else:
for i in simpleList:
if dig % i == 0:
if dig//i in simpleList:
outputList.append(i)
outputList.append(dig//i)
return (dig//i)
else:
outputList.append(i)
return (DoItSimple(dig//i))
mainList = []
for x in range(2,21):
outputList = []
DoItSimple(x)
for i in outputList:
if mainList.count(i) < outputList.count(i):
mainList.append(i)
print(mainList)
print(reduce(lambda x, y: x * y, mainList))
elapsed = (time.time() - start)
print("result returned after {0} seconds." .format(elapsed))
"""
[2, 3, 2, 5, 7, 2, 3, 11, 13, 2, 17, 19]
232792560
result returned after 0.0 seconds.
"""


По поводу сайта https://projecteuler.net/problem=N: для перехода к новому заданию меняем N на номер "проблемы"

неділя, 31 липня 2016 р.

Как убрать метод ввода РУС-US в windows 10

У меня данная проблема проявилась при удаленном подключении к моему рабочему компьютеру. Вот как она выглядит:
Добавляя и удаляя разные языки в панели инструментов ни к чему не привели. Погуглив я нашел вот такое решение:
В регистре, в [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout] добавить ключ "IgnoreRemoteKeyboardLayout"=dword:00000001

середа, 30 березня 2016 р.

Определяем блокирующие сессии

Запрос не мой. Помогает, если не могу скомпилировать пакет - находим блокирующую сессию и киляем ее. Вылаживаю, что бы был под рукой.

select distinct orakill from (
 select
        /*+ ordered */
        w1.sid waiting_session,
        h1.sid holding_session,
        w.kgllktype lock_or_pin,
        w.kgllkhdl address,
       (
         select 'ALTER SYSTEM DISCONNECT SESSION ''' || s.SID || ',' || s.SERIAL# || ''' IMMEDIATE;' sqll1
           from v$session s , v$process p
          where s.PADDR=p.ADDR and s.sid = h1.sid
       ) orakill,
        decode (h.kgllkmod, 0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive', 'Unknown' ) mode_held,
        decode (w.kgllkreq, 0, 'None', 1, 'Null', 2, 'Share', 3, 'Exclusive', 'Unknown' ) mode_requested
   from dba_kgllock w,
        dba_kgllock h,
        v$session w1,
        v$session h1
  where ( ( (h.kgllkmod != 0)
    and (h.kgllkmod     != 1)
    and ((h.kgllkreq     = 0)
     or (h.kgllkreq      = 1)) )
    and ( ((w.kgllkmod   = 0)
     or (w.kgllkmod      = 1))
    and ((w.kgllkreq    != 0)
    and (w.kgllkreq     != 1)) ) )
    and w.kgllktype      = h.kgllktype
    and w.kgllkhdl       = h.kgllkhdl
    and w.kgllkuse       = w1.saddr
    and h.kgllkuse       = h1.saddr
)

Пересоздание отключенного триггера включает его

Сегодня столкнулись с проблемой - начала выполняться лишняя проверка. Оказалось, что проверка выполнялась в триггере, который уже очень давно был disable, а сейчас он enable. Посмотрели по логам: один из наших программистов внес изменения в функцию и решил везде, где вызывается эта функция внести те же изменения. Поиск всех мест вызовов он проводил через поиск в PL/SQL Developer. Наш триггер тоже попал в результаты поиска. Проблема только в том, что в окне поиска PL/SQL Developer не пишется, что триггер отключен. И вот, он открыл на редактирование триггер с формы поиска, внес корректировки и нажал F8 (компил). После этого триггер стал enable.
По-умолчанию триггеры создаются сразу включенными. Только после создания их статус можно поменять через ALTER TRIGGER. Начиная с 11 версии Оракла можно явно, при создании, задавать в каком статусе будет создан этот триггер.
Наш триггер начинался с текста:
CREATE OR REPLACE TRIGGER ...
И оказывается, что при REPLACE также происходит включение триггера.

вівторок, 22 березня 2016 р.

Второй раз запрос выполняется намного дольше первого или Cardinality feedback

Недавно столкнулся с проблемой, когда запрос первый раз выполняется за 1 секунду, а второй и последующие разы за 30 секунд. Если добавить пробел или поменять регистр любой буквы в запросе, что бы oracle вновь сделал парсинг - то запрос снова выполняется за 1 секунду. Поиски привели меня к Cardinality feedback. В двух словах, это фича, которая позволяет оптимизатору учится на своих ошибках. То есть при первом выполнении делается предполагаемая оценка, а в процессе выполнения собирается реальная оценка и если они отличаются - правильная оценка сохраняется для последующего использования. В следующий раз, когда запрос выполняется, то он будет оптимизирован снова и на этот раз оптимизатор будет использовать скорректированные оценки вместо своих обычных оценок.
В моем случае это приводило к зависаниям при последующих вызовах запроса. И что бы отключить фичу можно использовать либо параметр сессии:
alter session set "_OPTIMIZER_USE_FEEDBACK"=FALSE;
либо хинт:
/*+ opt_param('_OPTIMIZER_USE_FEEDBACK','FALSE') */

 

понеділок, 14 березня 2016 р.

Raspberry Pi & PIR-датчик & перемычка

Купил себе на новый год "малинку" и сразу решил, что соединю ее с датчиком движения, прикручу ее где-то в коридоре и, в случае, когда кто-то посторонний будет шастать - буду отправлять себе смс, что в квартире есть движение.
Вот такая модель пришла: https://www.raspberrypi.org/products/raspberry-pi-2-model-b/
Датчик движения hc-sr501 и пару проводков мама-мама купил в местном интернет-магазине.
Когда все детальки были собраны, свободное время выделено, я нашел две статьи, по которым планировал научиться только детектить движение:
https://www.raspberrypi.org/learning/parent-detector/worksheet/

http://diyhacking.com/raspberry-pi-gpio-control/
О том, как установить операционку писать не буду, в интернете есть много статей.
Подключил датчик к Raspberry, как описано в первой статье, оттуда же скопировал скрипт. Запускаю... На мониторе пишет, что движение есть, хотя я до запуска, специально, развернул датчик в стену. Ну, думаю, стена мешает - повернул в пустой коридор. Все равно пишет, что есть движение. Подумал, что допустил ошибку в скрипте - проверил, все правильно. В общем пробовал, я и так и сяк - датчик выдает, что движение есть и хоть ты тресни. На самом датчике есть два винтика, которые регулируют чувствительность и время реагирование на движение. Покрутил и один и второй - то же самое "Есть движение". Подумал, что датчик поломанный.
Попробовал во время выполнения скрипта отсоединить провод от GP4 - появилась надпись "Движения нет". Ага, значит датчик исправен. Решил покопаться в интернете: перепробовал и дополнительные параметры в процедурах библиотеки GPIO, и подключение к другим пинам, и другие скрипты - результат тот же.
В итоге на поиски в интернете потратил около 3 часов, а результата нет.
Захожу еще на один форум, где люди кидали ссылки с алиэкспресса/ибея на датчики движения, которые они используют. В основном это были hc-sr501, точно такие как и у меня. Решил узнать сколько стоят датчики в Китае (свой брал в Киеве) - открываю ссылку, смотрю цену, смотрю фотки датчика и вижу, что у моего датчика расположение конденсаторов другое. У меня по одному конденсатору с каждого угла, а на фотке тоже 4 конденсатора, только 2 из них находятся рядом. Решил найти такую же модель, как и у меня. По одной из ссылок на ибей нашел "мой" датчик, но самое главное на картинке было описание некоторых элементов датчика:
  
Видите слева перемычку и 3 пина, и подпись repeatable trigger - как вы уже наверное догадались, у меня перемычка стояла в положении non-repeatable trigger. Поменял и ВСЕ ЗАРАБОТАЛО. Я был счастлив =)
Позже я нашел еще несколько картинок, где положения перемычки значились как "L"(Low) и "H"(High)-position.