๐Ÿ“ฆ robhogan / pygattlib

๐Ÿ“„ bindings.cpp ยท 117 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117// -*- mode: c++; coding: utf-8; tab-width: 4 -*-

// Copyright (C) 2014, Oscar Acena <oscaracena@gmail.com>
// This software is under the terms of GPLv3 or later.

#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>

#include "gattlib.h"
#include "gattservices.h"

using namespace boost::python;

class GATTResponseCb : public GATTResponse {
public:
	GATTResponseCb(PyObject* p) : self(p) {
	}

	// to be called from c++ side
	void on_response(const std::string data) {
		try {
			PyGILState_STATE state = PyGILState_Ensure();
			call_method<void>(self, "on_response", data);
			PyGILState_Release(state);
		} catch(error_already_set const&) {
			PyErr_Print();
		}
	}

	// to be called from python side
	static void default_on_response(GATTResponse& self_, const std::string data) {
		self_.GATTResponse::on_response(data);
	}

private:
	PyObject* self;
};

class GATTRequesterCb : public GATTRequester {
public:
	GATTRequesterCb(PyObject* p, std::string address, bool do_connect=true) :
		GATTRequester(address, do_connect),
		self(p) {
	}

	// to be called from c++ side
	void on_notification(const uint16_t handle, const std::string data) {
		try {
			PyGILState_STATE state = PyGILState_Ensure();
			call_method<void>(self, "on_notification", handle, data);
			PyGILState_Release(state);
		} catch(error_already_set const&) {
			PyErr_Print();
		}
	}

	// to be called from python side
	static void default_on_notification(GATTRequester& self_,
										const uint16_t handle,
										const std::string data) {
		self_.GATTRequester::on_notification(handle, data);
	}

	// to be called from c++ side
	void on_indication(const uint16_t handle, const std::string data) {
		try {
			PyGILState_STATE state = PyGILState_Ensure();
			call_method<void>(self, "on_indication", handle, data);
			PyGILState_Release(state);
		} catch(error_already_set const&) {
			PyErr_Print();
		}
	}

	// to be called from python side
	static void default_on_indication(GATTRequester& self_,
										const uint16_t handle,
										const std::string data) {
		self_.GATTRequester::on_indication(handle, data);
	}

private:
	PyObject* self;
};

BOOST_PYTHON_MODULE(gattlib) {

	register_ptr_to_python<GATTRequester*>();

	class_<GATTRequester, boost::noncopyable, GATTRequesterCb>
		("GATTRequester", init<std::string, optional<bool> >())

		.def("connect", &GATTRequester::connect)
		.def("is_connected", &GATTRequester::is_connected)
		.def("disconnect", &GATTRequester::disconnect)
		.def("read_by_handle", &GATTRequester::read_by_handle)
		.def("read_by_handle_async", &GATTRequester::read_by_handle_async)
		.def("read_by_uuid", &GATTRequester::read_by_uuid)
		.def("read_by_uuid_async", &GATTRequester::read_by_uuid_async)
		.def("write_by_handle", &GATTRequester::write_by_handle)
		.def("write_by_handle_async", &GATTRequester::write_by_handle_async)
		.def("on_notification", &GATTRequesterCb::default_on_notification)
		.def("on_indication", &GATTRequesterCb::default_on_indication)
		;

	register_ptr_to_python<GATTResponse*>();

	class_<GATTResponse, boost::noncopyable, GATTResponseCb>("GATTResponse")
		.def("received", &GATTResponse::received)
		.def("on_response", &GATTResponseCb::default_on_response);
		;

	class_<DiscoveryService>("DiscoveryService", init<std::string>())
		.def("discover", &DiscoveryService::discover)
		;
}