1

Python библиотека для Remote Api от Gurtam

Topic: Python библиотека для Remote Api от Gurtam

C недавнего времени на сервисе GitHub (хостинга проектов и их совместная разработка) доступна python библиотека  для работы на сервере с remote API.

Ссылка на страницу: https://github.com/wialon/python-wialon

Denis Strakh, Gurtam
2

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

О, круто. Классная задумка. Вот бы еще на Яве че-нить сделали wink

3

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Java в работе

Denis Strakh, Gurtam
4

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

stde wrote:

Java в работе

Вау! Я тапер прям уся горю в нетерпении... Испробовать хоцца.

5

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Здравствуйте.
Подскажите как использовать данный пакет:


Взял сорцы. Проверил на тестовом - работает.
Теперь решил использовать свои логин и пароль, изменил в классе

class Wialon(object):
    def __init__(self, scheme='http',  host="hst-api.wialon.com", port=80, sid=None, **extra_params):

значение параметра host на свой.  Пытаюсь подконнектиться - не идет. 

Предположения:
1) Не верно указываю свой хост
2) Не подключен sdk
3) Что-то еще?

С чего рекомендуете начать расследование?

P.S. Если заходит через браузер на мой хост, то через форму заходит спокойно.

6

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

SapronovAlexander

Здравствуйте.

По предположениям:

Первое вполне может быть. (Отпишите в личку  для проверки вместе с логином и паролем).
По второму пункту - модуль sdk должен быть подключен иначе при попытки логина будет возвращен код ошибки 7 (Access denied).
По третьему - маловероятно - думаю проблемы в вышеуказанных пунктах.

7

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Возможно ли привести на python пример search_items с условиями поиска? Например, вывести все доступные машины.

ООО "Курс"
www.gpskurs.com
8

Python библиотека для Remote Api от Gurtam

(edited by chal 02/09/2013 08:45:34)

Re: Python библиотека для Remote Api от Gurtam

nbush

from wialon import Wialon, flags

def main():    
    wialon = Wialon()
    try:
        login = wialon.core_login(user='wialon_test', password='test')        
    except WialonError as e:
        print e
        return
    wialon.sid = login['eid']
    
    spec = {
        'itemsType': 'avl_unit',    
        'propName': 'sys_name',    
        'propValueMask': '*',    
        'sortType': 'sys_name'
    }
    interval = {"from": 0, "to": 0}
    try:
        units = wialon.core_search_items(spec=spec, force=1, flags=flags.ITEM_DATAFLAG_BASE, **interval)
    except WialonError as e:
        print e
        return

    print units

if __name__ == '__main__':
    main()
9

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Спасибо
Просто я пробовал вызов типа

units = wialon.core_search_items(spec=spec, force=1, from = 0, to=0, flags=flags.ITEM_DATAFLAG_BASE)

Понятно, при этом python ругался на ключевое слово from в параметрах smile

ООО "Курс"
www.gpskurs.com
10

Python библиотека для Remote Api от Gurtam

(edited by solveMe 12/01/2014 14:50:11)

Re: Python библиотека для Remote Api от Gurtam

Нашел небольшой баг. В функции __unicode__() класса WialonError при каждом вызове (а следовательно и функций __str__() , __repr__()) будет наращиваться значение self._text на строку error[self._code]. Т.е. будет такой вывод например:

WialonError(Error performing request Ho-ho (5))
WialonError(Error performing request Error performing request Ho-ho (5))
WialonError(Error performing request Error performing request Error performing request Ho-ho (5))

Я решил что пусть self._text остается таки каким его передали в конструктор и поправил это следующи образом:

    def __unicode__(self):
        if (self._code in wError.errors):
            explanation = " ".join([wError.errors[self._code], self._text])
        message = u'{explanation} ({code})'.format(explanation=explanation, code=self._code)
        return u'WialonError({message})'.format(message=message)

Вот собственно и все. Кстати наверняка у автора либы будут мысли получше чем мои.

P.S. Очень понравилась ваша идея с вызовом команд Виалону, как будто они методы экземпляра Wialon(). Я ввиду своей неопытности в ближайшие года бы до такого не додумался.

11

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

solveMe wrote:

Нашел небольшой баг. В функции __unicode__() класса WialonError при каждом вызове (а следовательно и функций __str__() , __repr__()) будет наращиваться значение self._text на строку error[self._code]. Т.е. будет такой вывод например:

WialonError(Error performing request Ho-ho (5))
WialonError(Error performing request Error performing request Ho-ho (5))
WialonError(Error performing request Error performing request Error performing request Ho-ho (5))

Я решил что пусть self._text остается таки каким его передали в конструктор и поправил это следующи образом:

    def __unicode__(self):
        if (self._code in wError.errors):
            explanation = " ".join([wError.errors[self._code], self._text])
        message = u'{explanation} ({code})'.format(explanation=explanation, code=self._code)
        return u'WialonError({message})'.format(message=message)

Вот собственно и все. Кстати наверняка у автора либы будут мысли получше чем мои.

P.S. Очень понравилась ваша идея с вызовом команд Виалону, как будто они методы экземпляра Wialon(). Я ввиду своей неопытности в ближайшие года бы до такого не додумался.

Да, действительно есть такой баг. И ваше решение вполне подходит. Спасибо.

12

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Сегодня просматривал код данной библиотеки и заступорился на методе getattr(...). В частности никак не могу понять что делает данное выражение:

return get.__get__(self)

Ну т.е. я понимаю что оно возвращает в итоге функцию которую нужно вызвать вместо Wialon.action_name(...). Но на каких механизмах основывается работа данного кода понять не могу. Почитал про дескрипторы Python (метод __get__() вроде только для них применим), но осталось недопонимание откуда у метода

def get(self, *args, **kwargs)

взялся метод __get__()? Он ведь вроде по умолчанию не существует и его необходимо переопределять, да и вызывается он тоже неявно.
Был бы признателен если бы кто-нибудь объяснил где мои рассуждения свернули не туда. Интерес у меня чисто академический так сказать. Так получилось что подвернулась данная библиотека по работе, а я с Python'ом даже не то чтобы на "Вы", а скорее даже на "Ваше превосходительство" поэтому решил, что разбор использующихся тут приемов будет хорошим началом для изучения языка.

13

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Библиотеку писал не я, но ответить попробую. Академический интерес заразителен)

solveMe wrote:

откуда ... взялся метод __get__()? Он ведь вроде по умолчанию не существует и его необходимо переопределять ... да и вызывается он тоже неявно

Простая проверка показывает что метод очень даже существует у обычной функции.

>>> def test(var): print var
>>> test.__get__
<method-wrapper '__get__' of function object at 0x7f4f75798320>
>>>test.__get__('go')
<bound method ?.test of 'go'>

Документация гласит, что данный метод вызывается для получения атрибута owner класса, т.е. в нашем случае у Wialon. И вызвать функцию явно никто не запрещает.

Вообще мне очень нравится идея вызова не объявленных явно методов. Логика примерно следующая (на примере 'core_login'):
1) создается объект wialon класса Wialon
2) вызывается wialon.core_login(...)
3) функция 'core_login' явно не объявлена - вызывается wialon.__getattr__(self, 'core_login')
4) объявляется функция get(), которая по сути вызывает метод call('core/login')
5) вызывается get.__get__(...), которая вызывает get() owner'a (т.е. wialon)
6) результат ретурнится

Та же логика в библиотеке php-wialon, но выглядит прозрачнее)

14

Python библиотека для Remote Api от Gurtam

(edited by solveMe 11/02/2014 13:59:52)

Re: Python библиотека для Remote Api от Gurtam

Большое спасибо за ответ. Оказывается мой больной разум, все это время глядя в документации на слово owner, воспринимал его как parent. Остался непонятен только один момент: если в функции __getattr__(..) мы подсовываем вместо вызванной функции метод call() то зачем было запиливать функцию get и потом вызывать get.__get__()? Можно ли сразу напрямую сделать так:

def __getattr__(self, action_name):
     return self.call

Или я опять что-то упустил?

15

Python библиотека для Remote Api от Gurtam

(edited by chal 11/02/2014 19:18:57)

Re: Python библиотека для Remote Api от Gurtam

Спасибо за ваш интерес.

Метод __getattr__http://u.to/vi83Bg вызывается, если не найден подходящий метод (свойство) в объекте или в классах родителях. И, следовательно, он должен вернуть либо значение, если это свойство объекта или, так называемый, callable объект, что и просходит в нашем случаи. Этот callable объект и будет вызываться с параметрами. Пример ниже.

wialon_api = Wialon()
result = wialon_api.core_login(user='wialon_test', password='test')

Т.е. в цепочка вызова будет такая:
- __getattr__(self, 'core_login') - который и должен вернуть callable объект - назовем его callable_login
- вызовется callable_login в который, собственно, и передастся параметры user и password в словаре.

Вот для того, что бы __getattr__ и вернул callable объект и нужна нижеуказанная манипуляция.

def __getattr__(self, action_name):
        """
        Enable the calling of Wialon API methods through Python method calls
        of the same name.
        """
        def get(self, *args, **kwargs):
            return self.call(action_name, *args, **kwargs)

        return get.__get__(self)

Про __get__ можно почитать по ссылке http://u.to/lTA3Bg.

А по поводу вызова напрямую:

def __getattr__(self, action_name):
        return self.call

В таком случаи в метод call ни как не передается action_name. Можно было бы сделать это так:

from  functools import partial

def __getattr__(self, action_name):
        return partial(self.call, action_name)

Но мне, как автору, решение, которое и реализовано, показалось более прозначным и близким smile

Надеюсь вам стало понятнее.

16

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

chal wrote:

nbush

from wialon import Wialon, flags

def main():    
    wialon = Wialon()
    try:
        login = wialon.core_login(user='wialon_test', password='test')        
    except WialonError as e:
        print e
        return
    wialon.sid = login['eid']
    
    spec = {
        'itemsType': 'avl_unit',    
        'propName': 'sys_name',    
        'propValueMask': '*',    
        'sortType': 'sys_name'
    }
    interval = {"from": 0, "to": 0}
    try:
        units = wialon.core_search_items(spec=spec, force=1, flags=flags.ITEM_DATAFLAG_BASE, **interval)
    except WialonError as e:
        print e
        return

    print units

if __name__ == '__main__':
    main()

Добрый день,
Данный пример проверил, работает.

По аналогии пытаюсь выполнить загрузку сообщений, пример взят с документации https://sdk.wialon.com/wiki/ru/sidebar/ … s/messages
Далее собираю в следующий скрипт:

# -*- coding: utf-8 -*-
from wialon import Wialon, WialonError, flags
def main():    
    wialon = Wialon()
    try:
        result = wialon.token_login(token='token')        
    except WialonError as e:
        print e
        return
    wialon.sid = result['eid']

    params = {"itemId":928675,"timeFrom":1478147204,"timeTo":1478518392,"flags":0x0000,"flagsMask":0xFF00,"loadCount":0xffffffff}

    try:
        units = wialon.messages_load_interval(params)
    except WialonError as e:
        print e
        return
    print units
if __name__ == '__main__':
    main()

Вопрос, что тут не правильно, подскажите пожалуйста..

17

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Здравствуйте, togachev!

units = wialon.messages_load_interval(params)

Вам необходимо распаковать params при передаче функции:

units = wialon.messages_load_interval(**params)
18

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

asal wrote:

Здравствуйте, togachev!

units = wialon.messages_load_interval(params)

Вам необходимо распаковать params при передаче функции:

units = wialon.messages_load_interval(**params)

Сработало!
Спасибо!

19

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

смотрю сейчас на строчку

wialon.sid = login['eid']

очередная магия ?

"eid":<long>,    /* login operations count of current user */

подпись сломали .. впрочем не удивительно
20

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

tdt66 wrote:

смотрю сейчас на строчку

wialon.sid = login['eid']

очередная магия ?

"eid":<long>,    /* login operations count of current user */

В eid идентификатор сессии содержится и, видимо, в Pro он был просто числом.

В актуальной версии:

"eid":<text>,            /* session ID */

Вопрос, почему в ответе при логине он называется eid, а в запросы подаётся как sid — интересный.

21

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Здравствуйте. Подскажите, пожалуйста, как получить значения из таблицы отчета. Привожу свой код, который, к сожалению, выдает ошибки. Отчет units выполняется и выводит список таблиц, мне нужно получить данные из третьей таблицы, что я и пытаюсь сделать с помощью units1 = wialon.report_select_result_rows.

from wialon import Wialon, flags
import json
def main():    
    wialon = Wialon()
    try:
        login = wialon.token_login(token='***')        
    except WialonError as e:
        print (e)
        return
    wialon.sid = login['eid']

                            
    try:
        units = wialon.report_exec_report({
        'reportResourceId': 13503585,    
        'reportTemplateId': 8,    
        'reportObjectId': 13676716,    
        'reportObjectSecId': 0,
        'interval':{'from':1554836400,'to':1554919200,'flags':0x00}})
        
         units1 = wialon.report_select_result_rows({
            'tableIndex':2,
            'config':{
            'type':'range',
            'data':{
                'from':1554836400,
                'to':1554919200,
                'level':2}}})  
    except WialonError as e:
        print (e)
        return
      
    print (units['reportResult']['tables'][2])
    print (units1)
if __name__ == '__main__':
    main()
22

Python библиотека для Remote Api от Gurtam

Re: Python библиотека для Remote Api от Gurtam

Добрый день тт.

Из замечаний:
1) Нет импорта WialonError;
2) Не верно передаются параметры в report_exec_report и report_select_result_rows;
3) Вы не делаете logout и из-за этого у Вас в будущем могут быть проблемы при частом использовании скрипта (много активных сессий);
4) В report_select_result_rows не верный параметры from и to, Вы передаете время, а это на самом деле индексы строк отчета

+ Пример правильной работы
from wialon import Wialon, WialonError


TOKEN = '...'


def execute_report(wialon):

    report_params = {
        'reportResourceId': 13503585,
        'reportTemplateId': 8,
        'reportObjectId': 13676716,
        'reportObjectSecId': 0,
        'reportTemplate': None,
        'interval': {
            # from - unix timestamp
            'from': 1554836400,
            # to - unix timestamp
            'to': 1554919200,
            'flags': 0
        }
    }

    units = wialon.report_exec_report(**report_params)

    result_rows_params = {
        'tableIndex': 2,
        'config': {
            'type': 'range',
            'data': {
                # from - index of first row, not a unix timestamp
                'from': 0,  # This is jsut for example, please change it
                # to - index of last row, not a unix timestamp
                'to': 10,  # This is jsut for example, please change it
                'level': 2
            }
        }
    }

    units_rows = wialon.report_select_result_rows(**result_rows_params)

    print(units['reportResult']['tables'][2])
    print(units_rows)


def main():
    wialon = Wialon()

    try:
        login = wialon.token_login(token=TOKEN)
    except WialonError as e:
        print("Error while login:", e)
        return

    wialon.sid = login['eid']

    try:
        execute_report(wialon)
    except WialonError as e:
        print("Error while execturing report:", e)

    # logout is necessary, for preventing error with a lot of session from one ip
    try:
        wialon.core_logout()
    except WialonError as e:
        print("Error while logout")


if __name__ == '__main__':
    main()