القرصنة CAN ناقل السيارات للتحكم الصوتي



السيارة الحديثة ليست وسيلة نقل فحسب ، بل هي أيضًا أداة متقدمة مع وظائف الوسائط المتعددة ونظام تحكم إلكتروني للوحدات ومجموعة من أجهزة الاستشعار. يقدم العديد من مصنعي السيارات وظائف مساعدي الحركة ، ومساعدي وقوف السيارات ، ومراقبة السيارة والتحكم من الهاتف. هذا ممكن بسبب استخدام حافلة CAN في السيارة التي تتصل بها جميع الأنظمة: المحرك ، نظام الفرامل ، عجلة القيادة ، الوسائط المتعددة ، المناخ ، إلخ.

سيارتي 2011 سكودا اوكتافيا. لا يوفر إمكانات التحكم من الهاتف ، لذلك قررت إصلاح هذا العيب ، وفي الوقت نفسه أضف وظيفة التحكم الصوتي. كبوابة بين ناقل CAN والهاتف ، أستخدم Raspberry Pi مع درع CAN BUS وموجه TP-Link WiFi. تم إغلاق بروتوكول الاتصال الخاص بالركام التلقائي ، وردت فولكس واجن على جميع رسائلي مع توثيق البروتوكول. لذلك ، فإن الطريقة الوحيدة لمعرفة كيفية تواصل الأجهزة في السيارات ومعرفة كيفية إدارتها هي الهندسة العكسية لبروتوكول CAN لحافلة VW.

تصرفت على مراحل:

  1. تطوير درع CAN ل Raspberry Pi
  2. تثبيت برنامج للعمل مع ناقل CAN
  3. الاتصال بحافلة CAN للسيارة
  4. تطوير الشم ودراسة بروتوكول ناقل CAN
  5. تطوير تطبيق الهاتف
  6. التحكم الصوتي مع Homekit و Siri

في نهاية نافذة التحكم الصوتي بالفيديو.

تطوير درع CAN ل Raspberry Pi


هنا ، تم أخذ مخطط الدرع بواسطة lnxpps.de/rpie ، وهناك أيضًا وصف للاستنتاجات ، يتم استخدام دائرتين دقيقتين MCP2515 و MCP2551 للتواصل مع CAN. يتم توصيل سلكين CAN-High و CAN-Low بالدرع. في SprintLayout 6 ، قمت بنشر اللوحة ، يمكن لأي شخص أن يأتي في CANBoardRPi.lay سهل الاستخدام (في صورة العنوان ، النموذج الأولي للدرع على لوحة التوصيل).





تثبيت برنامج للعمل مع ناقل CAN


في Raspbian البالغ من العمر عامين ، كنت بحاجة إلى تصحيح bcm2708.c لإضافة دعم CAN (ربما هذا غير مطلوب الآن). للعمل مع ناقل CAN ، تحتاج إلى تثبيت حزمة الأداة المساعدة can-utils من github.com/linux-can/can-utils ، ثم تحميل الوحدات ورفع واجهة العلبة:

# initialize
insmod spi-bcm2708
insmod can
insmod can-dev
insmod can-raw
insmod can-bcm
insmod mcp251x
# Maerklin Gleisbox (60112 and 60113) uses 250000
# loopback mode for testing
ip link set can0 type can bitrate 125000 loopback on
ifconfig can0 up

نتحقق من أن واجهة CAN قد ارتفعت باستخدام الأمر ifconfig :



يمكنك التحقق من أن كل شيء يعمل عن طريق إرسال الأمر واستلامه.

في محطة واحدة نستمع:

root@raspberrypi ~ # candump any,0:0,#FFFFFFFF

في محطة أخرى ، نرسل:

root@raspberrypi ~ # cansend can0 123#deadbeef

يتم وصف عملية تثبيت أكثر تفصيلاً هنا lnxpps.de/rpie .

الاتصال بحافلة CAN للسيارة


بعد دراسة بسيطة للوثائق المفتوحة على حافلة VW CAN ، اكتشفت أنني أستخدم حافلتين.

ناقل CAN لوحدة الطاقة ، الذي ينقل البيانات بسرعة 500 كيلوبت / ثانية ، يربط جميع وحدات التحكم التي تخدم هذه الوحدة.

على سبيل المثال ، يمكن توصيل الأجهزة التالية بناقل CAN لوحدة الطاقة:

  • وحدة التحكم في المحرك
  • وحدة التحكم ABS
  • وحدة التحكم في استقرار الدورة ،
  • وحدة تحكم علبة التروس،
  • وحدة التحكم في الوسادة الهوائية،
  • مجموعة العدادات.

ناقل CAN لنظام الراحة ونظام أوامر المعلومات ، والذي يسمح بنقل البيانات بسرعة 100 كيلوبت / ثانية بين وحدات التحكم التي تخدم هذه الأنظمة.

على سبيل المثال ، يمكن
توصيل الأجهزة التالية بناقل CAN لنظام Comfort ونظام المعلومات <command :

  • وحدة تحكم مناخية أو نظام تكييف هواء ،
  • وحدات التحكم في أبواب السيارة ،
  • وحدة التحكم في نظام الراحة ،
  • وحدة تحكم مع شاشة عرض لنظام الراديو والملاحة.

الوصول إلى أول واحد يمكنك التحكم في حركة المرور (في إصداري على الميكانيكا ، يمكنك على الأقل التحكم في التحكم في السرعة) ، والوصول إلى الثاني يمكنك التحكم في الراديو ، والمناخ ، والقفل المركزي ، ونوافذ الطاقة ، والمصابيح الأمامية ، وما إلى ذلك.

يتم توصيل الحافلتين من خلال البوابة ، التي تقع في المنطقة الموجودة أسفل عجلة القيادة ، موصل OBD2 التشخيصي متصل أيضًا بالبوابة ، وللأسف لا يمكن سماع حركة المرور من الحافلتين من خلال موصل OBD2 ، يمكنك فقط إرسال أمر وطلب حالة. قررت أن أعمل فقط مع حافلة الراحة ، واتضح أن الموصل الموجود في باب السائق هو المكان الأكثر ملاءمة للاتصال بالحافلة.



يمكنني الآن الاستماع إلى كل ما يحدث في Comfort CAN وإرسال الأوامر.

تطوير الشم ودراسة بروتوكول ناقل CAN




بعد الوصول إلى الاستماع إلى ناقل CAN ، أحتاج إلى فك تشفير من يمر إلى من وماذا. يظهر تنسيق حزمة CAN في الشكل.



جميع الأدوات المساعدة من مجموعة can-utils نفسها قادرة على تحليل حزم CAN وتقديم معلومات مفيدة فقط ، وهي:

  • ID
  • طول البيانات
  • البيانات

يتم إرسال البيانات في شكل غير مشفر ، مما سهل دراسة البروتوكول. في Raspberry Pi ، كتبت خادمًا صغيرًا يعيد توجيه البيانات من candump إلى TCP / IP لتحليل تدفق البيانات على الكمبيوتر وإظهاره بشكل جميل.

بالنسبة لنظام macOS ، كتبت تطبيقًا بسيطًا يضيف لكل عنوان جهاز خلية إلى الجهاز اللوحي وفي هذه الخلية يمكنني بالفعل رؤية البيانات التي تتغير.



أضغط على زر نافذة الطاقة ، ووجدت خلية تتغير فيها البيانات ، ثم حددت الأوامر التي تتوافق مع الضغط لأسفل ، والضغط لأعلى ، وعقد ، واستمرار.

يمكنك التحقق من أن الأمر يعمل عن طريق إرساله من الجهاز ، على سبيل المثال ، الأمر لرفع الزجاج الأيسر لأعلى:

cansend can0 181#0200

الفرق التي تنقل الأجهزة عبر ناقل CAN في سيارات VAG (Skoda Octavia 2011) ، يتم تلقيها عن طريق الهندسة العكسية:

// Front Left Glass Up
181#0200
// Front Left Glass Down
181#0800
// Front Right Glass Up
181#2000
// Front Right Glass Down
181#8000
// Back Left Glass Up
181#0002
// Back Left Glass Down
181#0008
// Back Right Glass Up
181#0020
// Back Right Glass Down
181#0080
// Central Lock Open
291#09AA020000
// Central Lock Close
291#0955040000
// Update Light status of central lock (   /          ,       ,    )
291#0900000000

لقد كنت كسولًا جدًا لدراسة جميع الأجهزة الأخرى ، لذلك في هذه القائمة ، فقط ما كان مثيرًا للاهتمام بالنسبة لي.

تطوير تطبيق الهاتف


باستخدام الأوامر المستلمة ، كتبت تطبيقًا لـ iPhone يفتح / يغلق النوافذ ويتحكم في القفل المركزي.

على Raspberry Pi I أطلقت خادمين صغيرين ، يرسل الأول البيانات من candump إلى TCP / IP ، والثاني يتلقى أوامر من iPhone ويرسلها يمكن إرسالها.


مصادر تطبيق التحكم التلقائي لنظام التشغيل iOS
//
//  FirstViewController.m
//  Car Control
//
//  Created by Vitaliy Yurkin on 17.05.15.
//  Copyright (c) 2015 Vitaliy Yurkin. All rights reserved.
//

#import "FirstViewController.h"
#import "DataConnection.h"
#import "CommandConnection.h"

@interface FirstViewController () <DataConnectionDelegate>
@property (nonatomic, strong) DataConnection *dataConnection;
@property (nonatomic, strong) CommandConnection *commandConnection;
@property (weak, nonatomic) IBOutlet UILabel *Door_1;
@property (weak, nonatomic) IBOutlet UILabel *Door_2;
@property (weak, nonatomic) IBOutlet UILabel *Door_3;
@property (weak, nonatomic) IBOutlet UILabel *Door_4;
@property (weak, nonatomic) IBOutlet UIButton *CentralLock;
- (IBAction)lockUnlock:(UIButton *)sender;
@end

@implementation FirstViewController

- (void)viewDidLoad {
    self.dataConnection = [DataConnection new];
    self.dataConnection.delegate = self;
    [self.dataConnection connectToCanBus];
    
    self.commandConnection = [CommandConnection new];
    [self.commandConnection connectToCanBus];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)doorStatusChanged:(char)value {
    /*
     1 - Front Left Door
     2 - Front Right Door
     4 - Back Left Door
     8 - Back Right Door
     
     3 - Front Left&Right Door = 1 + 3
     5 - Front& Back left Door = 1 + 4
     */
    
    // Front Left Door
    if (value & 1) {
        self.Door_1.backgroundColor = [UIColor yellowColor];
        self.Door_1.text = @"";
        NSLog(@"1");
    }
    else {
        self.Door_1.backgroundColor = [UIColor lightGrayColor];
        self.Door_1.text = @"";
    }
    
    // Front Right Door
    if (value & 2) {
        self.Door_2.backgroundColor = [UIColor yellowColor];
        self.Door_2.text = @"";
        NSLog(@"2");
    }
    else {
        self.Door_2.backgroundColor = [UIColor lightGrayColor];
        self.Door_2.text = @"";
    }
    
    // Back Left Door
    if (value & 4) {
        self.Door_3.backgroundColor = [UIColor yellowColor];
        self.Door_3.text = @"";
        NSLog(@"4");
    }
    else {
        self.Door_3.backgroundColor = [UIColor lightGrayColor];
        self.Door_3.text = @"";
    }
    
    // Back Right Door
    if (value & 8) {
        self.Door_4.backgroundColor = [UIColor yellowColor];
        self.Door_4.text = @"";
        NSLog(@"8");
    }
    else {
        self.Door_4.backgroundColor = [UIColor lightGrayColor];
        self.Door_4.text = @"";
    }
}

BOOL firstStatusChange = YES;
BOOL lastStatus;

-(void) centralLockStatusChanged:(BOOL)status {
    // At first status changes set lastStatus variable
    if (firstStatusChange) {
        firstStatusChange = NO;
        // Invert status, to pass the next test
        lastStatus = !status;
    }
    
    // Change Lock image only if status changed
    if (!(lastStatus == status)) {
        // Check status
        if (status) {
            [self.CentralLock setBackgroundImage:[UIImage imageNamed:@"lock_close"] forState:UIControlStateNormal];
        }
        else {
            [self.CentralLock setBackgroundImage:[UIImage imageNamed:@"lock_open"] forState:UIControlStateNormal];
        }
        lastStatus = status;
    }
}


// Front Left Glass
- (IBAction)frontLeftUp:(UIButton *)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#0200"];
}
- (IBAction)frontLeftDown:(id)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#0800"];
}

// Front Right Glass
- (IBAction)frontRightUp:(UIButton *)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#2000"];
}
- (IBAction)frontRightDown:(id)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#8000"];
}

// Back Left Glass
- (IBAction)backLeftUp:(UIButton *)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#0002"];
}
- (IBAction)backLeftDown:(id)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#0008"];
}

// Back Right Glass
- (IBAction)backRightUp:(UIButton *)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#0020"];
}
- (IBAction)backtRightDown:(id)sender {
    [self.commandConnection sendMessage:@"cansend can0 181#0080"];
}

- (IBAction)lockUnlock:(UIButton *)sender {
    // If central lock closed
    if (lastStatus) {
        // Open
        [self.commandConnection sendMessage:@"cansend can0 291#09AA020000"];

        int64_t delayInSeconds = 1; // 1 sec
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [self.commandConnection sendMessage:@"cansend can0 291#0900000000"];
        });
        
    }
    else {
        // Close
        [self.commandConnection sendMessage:@"cansend can0 291#0955040000"];
        int64_t delayInSeconds = 1; // 1 sec
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [self.commandConnection sendMessage:@"cansend can0 291#0900000000"];
        });
    }
    
}
@end


هناك طريقة لا لكتابة تطبيقك للهاتف ، ولكن للاستفادة من الجاهز الجاهز من عالم المنازل الذكية ، ما عليك سوى تثبيت نظام التشغيل الآلي Z-Way على أمر Raspberry Pi :

wget -q -O - razberry.z-wave.me/install | sudo bash

بعد ذلك ، نضيف أجهزة CAN إلى نظام التشغيل الآلي Z-Way ، ونتحكم


في


منظم النوافذ كمفتاح عادي: تطبيقات الهاتف المحمول لـ Z-Way: ZWay Home Control و ZWay Control.

التحكم الصوتي مع Homekit و Siri


في إحدى مقالاتي ، وصفت عملية تثبيت Homebridge على Raspberry Pi للتحكم الصوتي في نظام أتمتة المنزل Z-Way . بعد تثبيت Homebridge ، ستتمكن من التحكم الصوتي باستخدام Siri. أنا متأكد من أنه بالنسبة لنظام Android ، هناك العديد من التطبيقات التي تسمح للصوت بإرسال طلبات HTTP للتحكم في Z-Way.

أرفق الفيديو إلى التحكم الصوتي لمنظم النوافذ.

Source: https://habr.com/ru/post/ar399043/


All Articles