pydbus 기본 예제

jalee·2023년 8월 6일
0

send_dbus.py

from pydbus import SessionBus
from gi.repository import GLib


class dbusService:
    '''
    DBus Service Example
    '''
    dbus = """
    <node>
        <interface name='com.example.dbusService'>
            <method name='send'>
                <arg type='i' name='distance' direction='out'/>
            </method>
        </interface>
    </node>
    """
    def __init__(self):
    	self.value = 100

    def send(self) -> int:
  		self.value += 1
        return self.value
            

bus = SessionBus()
bus.publish("com.example.dbusService", dbusService())
loop = GLib.MainLoop()
loop.run()

recv_dbus.py

from pydbus import SessionBus
import time
#from gi.repository import GLib

# Connect to the session bus
bus = SessionBus()
remote_object = bus.get('com.example.dbusService',"/com/example/dbusService")


while(1):
    
    print(remote_object.send())
    time.sleep(1)

위 코드와 같이 D-Bus 연결을 위해 세션버스 연결 및 경로(name)설정이 필요하다. 위 코드에서 경로는'com.example.dbusService' 이고 경로는 컴퓨터 내 공간이 아닌 D-bus의 이름을 할당해주는 것이기 때문에 컴퓨터 내부 경로와 혼동하지 말아야 한다.

받는쪽에서는 send측에서 정의한 경로를 통해 D-bus에 진입하고 메서드를 호출함으로써 데이터를 불러올 수 있다.

이유는 모르겠지만 send 파일을 처음에 만들 때 init 함수를 안만든채로 실행시켰더니 dbus가 실행되지 않았다. 꼭 필요한듯하다,,

다음 명령어를 통해 위 코드 실행이 가능하다.

python3 send_dbus.py &
python3 recv_dbus.py

다음은 CAN Data를 받아온 후 D-bus로 publish 하는 코드이다.

can_publish.py

import os
import can
from pydbus import SessionBus
from gi.repository import GLib

CAN_ID = "can0"

class dbusService:
    '''
    DBus Service Example
    '''
    dbus = """
    <node>
        <interface name='com.example.dbusService'>
            <method name='getDis'>
                <arg type='f' name='distance' direction='out'/>
            </method>
            <method name='getSpeed'>
                <arg type='f' name='speed' direction='out'/>
            </method>
        </interface>
    </node>
    """

    def __init__(self):
        os.system(f'sudo ifconfig {CAN_ID} down')
        os.system(f'sudo ip link set {CAN_ID} up type can bitrate 500000 dbitrate 8000000 restart-ms 1000 berr-reporting on fd on')
        self.can = can.interface.Bus(channel = CAN_ID, bustype = 'socketcan')


    def getDis(self) -> float:
        msg = self.can.recv();
        if msg is None:
            return "No message recieved"
        distance = msg.data[2] + msg.data[3]*256
        return distance

    def getSpeed(self) -> float:
        msg = self.can.recv();
        if msg is None:
            return "No message recieved"
        rpm = msg.data[0] + msg.data[1]*256
        speed = self.rpm2speed(rpm)
        return speed
            

bus = SessionBus()
bus.publish("com.example.dbusService", dbusService())

loop = GLib.MainLoop()
loop.run()

위 코드는 아두이노가 보낸 CAN Data를 Raspberry pi를 통해 받고, 이를 pydbus를 사용하여 dbus내에 전송하는 코드이다. 위 코드에는 init 함수를 통해 CAN 환경을 재정의 하고 받은 CAN 데이터를 복호화하는 과정이 추가되었다.아두이노에서 보내는 CAN 통신 속도는 500k이기 때문에 bitrate를 500으로 맞춰주었고,CAN data frame 내 [0],[1] 바이트에 rpm 값을, [2],[3] 바이트에 Distance값을 넣어 전송했기 때문에 위와같은 복호화 과정을 거쳤다.

다음은 CAN Data를 전송한 아두이노 코드이다.

#include <SPI.h>
#include <mcp2515.h>

//--------distance--------------------
const int TRIG_PIN = 7;
const int ECHO_PIN = 6;

//------------rpm---------------------
const byte PulsesPerRevolution = 2;
const unsigned long ZeroTimeout = 100000;
const byte numReadings = 2;
volatile unsigned long LastTimeWeMeasured;
volatile unsigned long PeriodBetweenPulses = ZeroTimeout + 1000;
volatile unsigned long PeriodAverage = ZeroTimeout + 1000;
unsigned long FrequencyRaw;
unsigned long FrequencyReal;
unsigned int PulseCounter = 1;
unsigned long PeriodSum;
unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;
unsigned long CurrentMicros = micros();
unsigned int AmountOfReadings = 1;
unsigned int ZeroDebouncingExtra;
unsigned long readings[numReadings];
unsigned long readIndex;  
unsigned long total; 
unsigned long average;

//-----------can----------------------------
struct can_frame speed;
MCP2515 mcp2515(9);  

long whatisDistance(){

  long duration, distance;
 
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  duration = pulseIn(ECHO_PIN,HIGH);
 
  // convert the time into a distance
  distance = duration / 29.1 / 2 ;
  return distance;

}

void Pulse_Event() {
  PeriodBetweenPulses = micros() - LastTimeWeMeasured;
  LastTimeWeMeasured = micros();
  if (PulseCounter >= AmountOfReadings)  {
    PeriodAverage = PeriodSum / AmountOfReadings;
    PulseCounter = 1;
    PeriodSum = PeriodBetweenPulses;
    int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);
    RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);
    AmountOfReadings = RemapedAmountOfReadings;
  } 
  else {
    PulseCounter++;
    PeriodSum = PeriodSum + PeriodBetweenPulses;
  }
}

long whatisRpm(){
  long RPM;
  LastTimeCycleMeasure = LastTimeWeMeasured;
  CurrentMicros = micros();
  if (CurrentMicros < LastTimeCycleMeasure) {
    LastTimeCycleMeasure = CurrentMicros;
  }
  FrequencyRaw = 10000000000 / PeriodAverage;
  if (PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra) {
    FrequencyRaw = 0;  // Set frequency as 0.
    ZeroDebouncingExtra = 2000;
  } else {
    ZeroDebouncingExtra = 0;
  }
  FrequencyReal = FrequencyRaw / 10000;

  RPM = FrequencyRaw / PulsesPerRevolution * 60;
  RPM = RPM / 10000;
  total = total - readings[readIndex];
  readings[readIndex] = RPM;
  total = total + readings[readIndex];
  readIndex = readIndex + 1;

  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;

  return RPM;
}

void setup() {
  Serial.begin(115200);
  //lcd.init();
  //lcd.backlight();

  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, RISING);
  delay(1000);

//-------------distance setting---------------
  pinMode(TRIG_PIN,OUTPUT);
  pinMode(ECHO_PIN,INPUT);

//-------------can setting-------------------
  mcp2515.reset();
  mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);
  mcp2515.setNormalMode();
  speed.can_id = 0x123;
  speed.can_dlc = 8;
  for(int i=0;i<8;i++){
    speed.data[i] = 0;
  }
}

void loop() {

  long distance = whatisDistance();
  long RPM = whatisRpm();

  speed.data[0] = RPM%256;
  speed.data[1] = RPM/256;
  speed.data[2] = distance%256;
  speed.data[3] = distance/256;

  for(int i=0;i<8;i++){
    Serial.print(speed.data[i]);
    Serial.print(" ");
  }

  Serial.println();
  mcp2515.sendMessage(&speed);
  Serial.print("RPM: ");
  Serial.print(RPM);
  Serial.print("  ");
  Serial.print("distance: ");
  Serial.println(distance);
  delay(200);
}

0개의 댓글