반응형

OpenPose 소스를 컴파일하고 실행해 보자.

 

CMake를 다운로드하고 설치한다.

 

CUDA Toolkit 11.1.1을 다운로드하고 설치한다.

 

권장옵션으로 설치한다.

 

cuDNN 8.1.0을 다운로드한다. (NVIDIA 로그인이 필요하다)

 

 

다운로드한 cuDNN 압축을 풀고 cuda 폴더를 위 경로에 복사한다.

 

적당한 디렉토리에 OpenPose를 클론한다.

 

git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose

cd openpose

git submodule update --init --recursive --remote

 

build 폴더를 만든다.

 

CMake를 실행하고 경로를 설정한다. 그리고 Configure를 클릭한다.

 

 

위와 같이 설정하고 Finish를 클릭한다.

 

Configuring이 끝나면 Generate를 클릭한다.

Python이나 Unity에서 사용한다면 옵션을 선택한다.

(Configure에서 x64를 선택했다면 64비트 Python이 필요하다)

 

OpenPose.sln을 실행한다.

 

Solution Configurations를 Release로 바꾸고 빌드한다.

빌드가 완료되면 실행(Ctrl+F5)한다. OpenPoseDemo가 실행된다.

 

 

Visual Studio 외부에서 OpenPoseDemo.exe나 다른 예제를 실행하려면 아래 파일과 폴더를 같은 폴더에 복사해야 한다.

 

bin 폴더의 모든 파일을 실행파일이 있는 폴더에 복사한다.

 

models 폴더를 실행파일이 있는 폴더에 복사한다.

 

예제에 따라 examples 폴더가 필요할 수도 있다.

 

 

생각보다 메모리가 많이 필요하다.

 

※ 참고

OpenPose Installation

반응형
Posted by J-sean
:
반응형

한텍 오실로스코프 2D42의 배터리를 교환해 보자.

 

몇 달 만에 켜보니 반응이 없다. 이럴 줄 알았다.

 

두꺼운 고무 케이스를 분리한다. 힘이 많이 들어간다.

 

뒷면 나사 4개만 풀면 쉽게 열 수 있다.

 

원래 들어 있던 배터리.

 

 

전압을 측정해 본다. 역시 죽기 직전이다. 다시 충전해서 살려도 금방 죽는다.

 

밸런싱한 새 배터리를 준비한다.

 

새 배터리를 넣어준다.

 

충전단자 옆 USB 포트는 아무것도 연결되어 있지 않다. 다른 모델을 위한 포트인 듯.

 

 

다시 조립하고 켜본다. 잘 된다.

 

사실 뒷면 거치대를 열고 나사 2개만 풀면 배터리 커버를 제거할 수 있다. 하지만 저 배터리 커버가 잘 안빠진다.

 

반응형
Posted by J-sean
:
반응형

MySQL(MariaDB)과 구글 차트를 연동해 보자.

 

아래 내용을 참고해 웹서버와 데이터베이스를 준비한다.

2021.08.25 - [Linux] - Linux(Ubuntu) Build Your Own Web Server - 리눅스(우분투)로 웹서버 만들기

2021.08.28 - [Linux] - Linux(Ubuntu) MariaDB(MySQL) Server Remote Access - 데이터베이스 원격 접속

(데이터베이스는 로컬로 사용하므로 원격 설정을 할 필요는 없다)

 

위와 같은 데이터베이스와 테이블을 생성한다.

 

시간, 온도, 습도 데이터를 적당히 입력한다.

 

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
<html>
<head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <!--
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
    -->
 
    <?php
        // 에러가 발생하면 내용 표시
        error_reporting(E_ALL);
        ini_set('display_errors''1');
 
        $mysql_host = "localhost";
        $mysql_user = "root";
        $mysql_password = "1234";
        $mysql_db = "test_db";
 
        $conn = mysqli_connect($mysql_host$mysql_user$mysql_password$mysql_db);
        if (!$conn) {
            die("Database Connect Error: " . mysqli_connect_error());
        }
            
        //echo "Database Connected.<br><br>";
            
        $sql = "SELECT * FROM test_tb";
        $result = mysqli_query($conn$sql);
        
        if (mysqli_num_rows($result> 0) {
            while ($row = mysqli_fetch_assoc($result)) {
                $data_array[] = $row;
            }
            $chart = json_encode($data_array);
        } else {
            echo "No Data";
        }
        
        //echo $chart;
 
        mysqli_close($conn);
    ?>
 
    <script type="text/javascript">
        google.charts.load('current', { packages: ['corechart''line'] });
        google.charts.setOnLoadCallback(drawChart);
        
        function drawChart() {
            var chart_array = <?php echo $chart; ?>;
            //console.log(JSON.stringify(chart_array))
            var header = ['dt''temp''humid'];
            var row = "";
            var rows = new Array();
            jQuery.each(chart_array, function(index, item) {
                row = [
                    item.dt,
                    Number(item.temp),
                    Number(item.humid)
                ];
                rows.push(row); 
            });
 
            var jsonData = [header].concat(rows);
            var data = new google.visualization.arrayToDataTable(jsonData);
            var options = {
                title: 'Temperaure & Humid',
                hAxis: {
                    title: 'Time'
                },
                series: {
                    0: { targetAxisIndex: 0 },
                    1: { targetAxisIndex: 1 }
                },
                vAxes: {
                    0: {
                        title: 'Temperature',
                        viewWindow: { min: -30, max: 50 }
                    },
                    1: {
                        title: 'Humid',
                        viewWindow: { min: 30, max: 100 }
                    }
                }
                //,
                //curveType: 'function',
                //legend: { position: 'bottom' }
            };
 
            var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
            chart.draw(data, options);
        }
    </script>
</head>
<body>
    <div id="chart_div" style="width: 900px; height: 500px"></div>
</body>
</html>
 

 

소스를 입력하고 웹서버에 저장한다.(/var/www/html/index.php)

 

웹서버에 접속하면 위와 같은 그래프가 표시된다.

 

 

X축 레이블을 좀 더 보기 편하게 바꾸고 테이블 차트도 추가해 보자.

 

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
<html>
<head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
    <!--
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
    -->
 
    <?php
        // 에러가 발생하면 내용 표시
        error_reporting(E_ALL);
        ini_set('display_errors''1');
 
        $mysql_host = "localhost";
        $mysql_user = "root";
        $mysql_password = "1234";
        $mysql_db = "test_db";
 
        $conn = mysqli_connect($mysql_host$mysql_user$mysql_password$mysql_db);
        if (!$conn) {
            die("Database Connect Error: " . mysqli_connect_error());
        }
            
        //echo "Database Connected.<br><br>";
            
        $sql = "SELECT * FROM test_tb";
        $result = mysqli_query($conn$sql);
        
        if (mysqli_num_rows($result> 0) {
            while ($row = mysqli_fetch_assoc($result)) {
                $data_array[] = $row;
            }
            $chart = json_encode($data_array);
        } else {
            echo "No Data";
        }
        
        //echo $chart;
 
        mysqli_close($conn);
    ?>
 
    <script type="text/javascript">
        google.charts.load('current', { packages: ['corechart''line'] });
        google.charts.load('current', { packages: ['table'] });
        google.charts.setOnLoadCallback(drawChart);
        
        function drawChart() {
            var chart_array = <?php echo $chart; ?>;
            //console.log(JSON.stringify(chart_array))
            var header = ['Date&Time(MM-DD HH:MM)''Temp''Humid'];
            var row = "";
            var rows = new Array();
            jQuery.each(chart_array, function(index, item) {
                row = [
                    item.dt.substr(511),  // 너무 긴 날짜 및 시간을 짧게 추출
                    Number(item.temp),
                    Number(item.humid)
                ];
                rows.push(row); 
            });
 
            var jsonData = [header].concat(rows);
            var data = new google.visualization.arrayToDataTable(jsonData);
 
            var lineChartOptions = {
                title: 'Temperaure & Humid',
                hAxis: {
                    title: 'Time',
                    showTextEvery: 4    // X축 레이블이 너무 많아 보기 힘드므로 4개마다 하나씩 표시
                },
                series: {
                    0: { targetAxisIndex: 0 },
                    1: { targetAxisIndex: 1 }
                },
                vAxes: {
                    0: {
                        title: 'Temperature',
                        viewWindow: { min: -30, max: 50 }
                    },
                    1: {
                        title: 'Humid',
                        viewWindow: { min: 30, max: 100 }
                    }
                }
                //,
                //curveType: 'function',
                //legend: { position: 'bottom' }
            };
 
            var lineChart = new google.visualization.LineChart(document.getElementById('lineChart_div'));
            lineChart.draw(data, lineChartOptions);
 
            // 테이블 차트
            var tableChartOptions = {
                showRowNumber: true,
                width: '40%',
                height: '20%'
            }
 
            var tableChart = new google.visualization.Table(document.getElementById('tableChart_div'));
            tableChart.draw(data, tableChartOptions);
        }
    </script>
</head>
<body>
    <div id="lineChart_div" style="width: 900px; height: 500px"></div>
    <div id="tableChart_div"></div>
</body>
</html>
 

 

소스를 수정하고 웹서버에 저장한다.(/var/www/html/index.php)

 

웹서버에 접속하면 위와 같은 그래프와 차트가 표시된다.

 

※ 참고

2022.05.05 - [Web Development] - Google Chart - 구글 차트 1

반응형
Posted by J-sean
:
반응형

구글 차트를 이용해 웹페이지에 그래프(Dual-Y Chart)를 그려보자.

 

서버가 필요하다면 아래 링크를 참고해 서버를 만든다.

2021.08.25 - [Linux] - Linux(Ubuntu) Build Your Own Web Server - 리눅스(우분투)로 웹서버 만들기

 

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
<html>
<head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
        google.charts.load('current', { packages: ['corechart''line'] });
        google.charts.setOnLoadCallback(drawChart);
 
        function drawChart() {
            var data = new google.visualization.DataTable();
            data.addColumn('datetime''Time');
            data.addColumn('number''Temperature');
            data.addColumn('number''Humid');
 
            data.addRows([
                // 00: 1월, 01: 2월, 02: 3월...
                [new Date(202203011130), 2570],
                [new Date(202203021130), 2672],
                [new Date(202203031130), 2775],
                [new Date(202203041130), 2977],
                [new Date(202203051130), 2474],
                [new Date(202203061130), 2671],
                [new Date(202203071130), 2974],
                [new Date(202203081130), 3172],
                [new Date(202203091130), 3369],
                [new Date(202203101130), 2975],
                [new Date(202203111130), 3272],
                [new Date(202203121130), 3171]
            ]);
 
            var options = {
                title: 'Temperaure & Humid',
                hAxis: {
                    title: 'Time'
                },
                series: {
                    0: { targetAxisIndex: 0 },
                    1: { targetAxisIndex: 1 }
                },
                vAxes: {
                    0: {
                        title: 'Temperature',
                        viewWindow: { min: -30, max: 50 }
                    },
                    1: {
                        title: 'Humid',
                        viewWindow: { min: 30, max: 100 }
                    }
                }
                //,
                //curveType: 'function',
                //legend: { position: 'bottom' }
            };
 
            var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
            chart.draw(data, options);
        }
    </script>
</head>
<body>
    <div id="chart_div" style="width: 900px; height: 500px"></div>
</body>
</html>
 

 

HTML소스를 입력하고 저장한다.

 

인터넷 브라우저로 열어보면 그래프가 나타난다.

 

※ 참고

Google Charts

반응형
Posted by J-sean
:

MySQL(MariaDB) Connector

Python 2022. 5. 5. 00:15 |
반응형

2018.11.19 - [Python] - PyMySQL

 

Python에서 원격으로 MySQL(MariaDB)을 사용해 보자.

아래 링크를 참고해 데이터베이스를 준비한다.

2021.08.28 - [Linux] - Linux(Ubuntu) MariaDB(MySQL) Server Remote Access - 데이터베이스 원격 접속

 

mysql-connector-python을 설치한다.

 

데이터베이스에는 위와 같은 데이터를 준비한다.

 

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
import mysql.connector
from mysql.connector import errorcode
 
try:
    cnx = mysql.connector.connect(host="192.168.171.20", user="root",
                                  passwd="1234", database="test_db",
                                  connection_timeout=5)
except mysql.connector.Error as err:
    if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
        print("Something is wrong with your user name or password")
    elif err.errno == errorcode.ER_BAD_DB_ERROR:
        print("Database does not exist")
    elif err.errno == 2003# 호스트 주소가 틀리거나 문제가 있다면
        print("Connection error(Timeout)")
    else:
        print(err)
else:   # 데이터베이스 접속 오류가 없다면
    cursor = cnx.cursor()
    
    query = ("SELECT * FROM test_tb")
    cursor.execute(query)
    for (id, name, age) in cursor:
        print("id: {}, name: {}, age: {}".format(id, name, age))
            
    #for row in cursor:
    #    print(row)
 
    cursor.close()
    cnx.close()
 

 

소스를 입력하고 실행한다.

 

데이터베이스의 내용이 출력된다.

 

※ 참고

MySQL Connector/Python Developer Guide

반응형
Posted by J-sean
:
반응형

안드로이드 리눅스 커널 명령을 실행해 보자.

 

레이아웃에 에디트박스, 버튼, 텍스트뷰를 적당히 배치한다.

 

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
package com.example.myapplication;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
public class MainActivity extends AppCompatActivity {
 
    EditText editText;
    Button button;
    TextView textView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        editText = findViewById(R.id.editTextTextPersonName);
        button = findViewById(R.id.button);
        textView = findViewById(R.id.textView);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                StringBuffer stringBuffer = new StringBuffer();
 
                java.lang.Process process;
                try {
                    process = Runtime.getRuntime().exec(editText.getText().toString());
                    process.waitFor();
                    // Causes the current thread to wait, if necessary, until the process
                    // represented by this Process object has terminated.
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    String line = "";
                    while ((line = bufferedReader.readLine()) != null) {
                        stringBuffer.append(line + "\n");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                String result = stringBuffer.toString();
                textView.setText(result);
            }
        });
    }
}
 

 

소스를 입력하고 빌드한다.

 

실행하면 위와같은 화면이 나타난다.

 

간단한 명령어를 입력하고 결과를 확인한다.

 

 

명령어 실행시 매번 새로운 프로세스에서 실행되기 때문에 연속적인 작업을 할 수 는 없다.

예) cd /proc, pwd를 차례로 실행해도 결과는 항상 /이다.

 

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
package com.example.myapplication;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
 
    EditText editText;
    Button button;
    TextView textView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        editText = findViewById(R.id.editTextTextPersonName);
        button = findViewById(R.id.button);
        textView = findViewById(R.id.textView);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    Runtime.getRuntime().exec(editText.getText().toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
 

 

소스를 위와 같이 바꾸고 input 명령어를 사용해 보자.

(process.waitFor() 를 사용하면 아래 예에서 제대로 동작하지 않는다)

 

input keyevent KEYCODE_BACK 명령을 실행하면 Back 버튼이 눌린것 처럼 동작한다.

 

input keyevent KEYCODE_CALL 명령을 실행하면 전화 화면이 나타난다.

※ 참고

KeyEvent

 

반응형
Posted by J-sean
:
반응형

2022.04.05 - [C#] - C# Joystick(Gamepad) Input Check - 조이스틱(게임패드) 입력 확인 1 의 내용을 참고하여 조금 더 간단히 조이스틱(게임패드) 입력을 확인해 보자.

 

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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Threading;
using System.Diagnostics;
 
using HidSharp;
using HidSharp.Utility;
using HidSharp.Reports;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            HidSharpDiagnostics.EnableTracing = true;
            HidSharpDiagnostics.PerformStrictChecks = true;
 
            DeviceList list = DeviceList.Local;
            list.Changed += (sender, e) => Console.WriteLine("Device list changed.");
 
            HidDevice[] hidDeviceList = list.GetHidDevices().ToArray();
 
            foreach (HidDevice dev in hidDeviceList)
            {
                if (!dev.ToString().Contains("gamepad"))
                {
                    Console.WriteLine(dev.GetProductName() + " is not a gamepad.");
                    continue;
                }
 
                try
                {
                    ReportDescriptor reportDescriptor = dev.GetReportDescriptor();
 
                    Debug.Assert(dev.GetMaxInputReportLength() == reportDescriptor.MaxInputReportLength);
                    Debug.Assert(dev.GetMaxOutputReportLength() == reportDescriptor.MaxOutputReportLength);
                    Debug.Assert(dev.GetMaxFeatureReportLength() == reportDescriptor.MaxFeatureReportLength);
 
                    foreach (DeviceItem deviceItem in reportDescriptor.DeviceItems)
                    {
                        {
                            HidStream hidStream;
                            if (dev.TryOpen(out hidStream))
                            {
                                Console.WriteLine(dev.GetProductName() + " opened.");
                                hidStream.ReadTimeout = Timeout.Infinite;
 
                                using (hidStream)
                                {
                                    byte[] inputReportBuffer = new byte[dev.GetMaxInputReportLength()];
                                    HidSharp.Reports.Input.HidDeviceInputReceiver inputReceiver =
                                        reportDescriptor.CreateHidDeviceInputReceiver();
                                    HidSharp.Reports.Input.DeviceItemInputParser inputParser =
                                        deviceItem.CreateDeviceItemInputParser();
 
                                    inputReceiver.Start(hidStream);
 
                                    while (true)
                                    {
                                        if (inputReceiver.WaitHandle.WaitOne(1000))
                                        {
                                            if (!inputReceiver.IsRunning) { break; } // Disconnected?
 
                                            Report report;
                                            while (inputReceiver.TryRead(inputReportBuffer, 0out report))
                                            {
                                                if (inputParser.TryParseReport(inputReportBuffer, 0, report) && inputParser.HasChanged)
                                                {
                                                    //inputParser.HasChanged는 버튼을 누르거나 놓는 등 상태가 변경되는 경우를 뜻한다.
 
                                                    //Console.WriteLine(BitConverter.ToString(inputReportBuffer));
 
                                                    if (inputReportBuffer[3== 0x00)
                                                    {
                                                        Console.WriteLine("Left");
                                                    }
                                                    else if (inputReportBuffer[3== 0xFF)
                                                    {
                                                        Console.WriteLine("Right");
                                                    }
                                                    else if (inputReportBuffer[4== 0x00)
                                                    {
                                                        Console.WriteLine("Up");
                                                    }
                                                    else if (inputReportBuffer[4== 0xFF)
                                                    {
                                                        Console.WriteLine("Down");
                                                    }
                                                    else if (inputReportBuffer[5== 0x1F)
                                                    {
                                                        Console.WriteLine("X");
                                                    }
                                                    else if (inputReportBuffer[5== 0x2F)
                                                    {
                                                        Console.WriteLine("A");
                                                    }
                                                    else if (inputReportBuffer[5== 0x4F)
                                                    {
                                                        Console.WriteLine("B");
                                                    }
                                                    else if (inputReportBuffer[5== 0x8F)
                                                    {
                                                        Console.WriteLine("Y");
                                                    }
                                                    else if (inputReportBuffer[6== 0x01)
                                                    {
                                                        Console.WriteLine("L Shoulder");
                                                    }
                                                    else if (inputReportBuffer[6== 0x02)
                                                    {
                                                        Console.WriteLine("R Shoulder");
                                                    }
                                                    else if (inputReportBuffer[6== 0x10)
                                                    {
                                                        Console.WriteLine("Select");
                                                    }
                                                    else if (inputReportBuffer[6== 0x20)
                                                    {
                                                        Console.WriteLine("Start");
                                                    }
                                                }
                                            }
                                        }
 
                                        if (Console.KeyAvailable)
                                        {
                                            ConsoleKeyInfo consoleKeyInfo = Console.ReadKey(true);
 
                                            if (consoleKeyInfo.Key == ConsoleKey.Escape)
                                            {
                                                Console.WriteLine("User stopped.");
                                                break;
                                                //hidStream.Close();
                                            }
                                        }
                                    }
                                }
 
                                Console.WriteLine("Gamepad closed.");
                            }
                            else
                            {
                                Console.WriteLine("Failed to open device.");
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

 

프로그램을 실행하고 게임패드의 버튼을 누르면 어떤 버튼이 눌리는지 표시된다.

 

반응형
Posted by J-sean
:
반응형

컴퓨터에 연결된 모든 HID(Human Interface Devices)를 확인하고 조이스틱(게임패드)의 입력을 체크해 보자.

 

HidSharp를 설치한다.

 

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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Threading;
using System.Diagnostics;
 
using HidSharp;
using HidSharp.Utility;
using HidSharp.Reports;
 
namespace ConsoleApp1
{
    class Program
    {
        static void WriteDeviceItemInputParserResult(HidSharp.Reports.Input.DeviceItemInputParser parser)
        {
            while (parser.HasChanged)
            {
                int changedIndex = parser.GetNextChangedIndex();
                DataValue previousDataValue = parser.GetPreviousValue(changedIndex);
                DataValue dataValue = parser.GetValue(changedIndex);
 
                Console.WriteLine(string.Format("  {0}: {1} -> {2}", (Usage)dataValue.Usages.FirstOrDefault(),
                    previousDataValue.GetPhysicalValue(), dataValue.GetPhysicalValue()));
            }
        }
 
        static void Main(string[] args)
        {
            HidSharpDiagnostics.EnableTracing = true;
            HidSharpDiagnostics.PerformStrictChecks = true;
 
            DeviceList list = DeviceList.Local;
            list.Changed += (sender, e) => Console.WriteLine("Device list changed.");
 
            Device[] allDeviceList = list.GetAllDevices().ToArray();
            Console.WriteLine("■ All device list:");
            foreach (Device dev in allDeviceList)
            {
                Console.WriteLine("- Name: " + dev.ToString() + "\n" + "  Path: " + dev.DevicePath);
            }
 
            Console.WriteLine("-----------------------------------------------");
 
            Stopwatch stopwatch = Stopwatch.StartNew();
            HidDevice[] hidDeviceList = list.GetHidDevices().ToArray();
 
            Console.WriteLine("■ HID device list (took {0} ms to get {1} devices):",
                              stopwatch.ElapsedMilliseconds, hidDeviceList.Length);
 
            foreach (HidDevice dev in hidDeviceList)
            {
                Console.WriteLine("- Name: " + dev);
                Console.WriteLine("  Path: " + dev.DevicePath);
 
                try
                {
                    ReportDescriptor reportDescriptor = dev.GetReportDescriptor();
 
                    // Lengths should match.
                    Debug.Assert(dev.GetMaxInputReportLength() == reportDescriptor.MaxInputReportLength);
                    Debug.Assert(dev.GetMaxOutputReportLength() == reportDescriptor.MaxOutputReportLength);
                    Debug.Assert(dev.GetMaxFeatureReportLength() == reportDescriptor.MaxFeatureReportLength);
 
                    foreach (DeviceItem deviceItem in reportDescriptor.DeviceItems)
                    {
                        foreach (uint usage in deviceItem.Usages.GetAllValues())
                        {
                            Console.WriteLine(string.Format("  Usage: {0:X4} {1}", usage, (Usage)usage));
                        }
 
                        {
                            Console.WriteLine("Opening device for 20 seconds...");
 
                            HidStream hidStream;
                            if (dev.TryOpen(out hidStream))
                            {
                                Console.WriteLine("Opened device.");
                                hidStream.ReadTimeout = Timeout.Infinite;
 
                                using (hidStream)
                                {
                                    byte[] inputReportBuffer = new byte[dev.GetMaxInputReportLength()];
                                    HidSharp.Reports.Input.HidDeviceInputReceiver inputReceiver = 
                                        reportDescriptor.CreateHidDeviceInputReceiver();
                                    HidSharp.Reports.Input.DeviceItemInputParser inputParser = 
                                        deviceItem.CreateDeviceItemInputParser();
 
                                    inputReceiver.Start(hidStream);
 
                                    int startTime = Environment.TickCount;
                                    while (true)
                                    {
                                        if (inputReceiver.WaitHandle.WaitOne(1000))
                                        {
                                            if (!inputReceiver.IsRunning) { break; } // Disconnected?
 
                                            Report report;
                                            while (inputReceiver.TryRead(inputReportBuffer, 0out report))
                                            {
                                                // Parse the report if possible.
                                                // This will return false if (for example) the report applies to a different DeviceItem.
                                                if (inputParser.TryParseReport(inputReportBuffer, 0, report))
                                                {
                                                    WriteDeviceItemInputParserResult(inputParser);
                                                }
                                            }
                                        }
 
                                        uint elapsedTime = (uint)(Environment.TickCount - startTime);
                                        if (elapsedTime >= 20000) { break; } // Stay open for 20 seconds.
                                    }
 
                                }
 
                                Console.WriteLine("Closed device.");
                            }
                            else
                            {
                                Console.WriteLine("Failed to open device.");
                            }
 
                            Console.WriteLine("  ---------------------------------------------");
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

 

프로그램을 실행하면 연결된 모든 디바이스와 HID가 표시되고 open 가능한 디바이스(usb gamepad)는 입력을 받아 표시한다.

포커스가 다른 프로그램에 있어도 디바이스의 입력을 확인 할 수 있다.

 

 

각 버튼이 눌렸을때 inputReportBuffer의 변화되는 내용을 확인해 보면 아래와 같다.

(첫 번째 바이트의 '01'은 Report ID인거 같다)

 

1
Console.WriteLine(BitConverter.ToString(inputReportBuffer));
 

 

01-80-80-7F-7F-0F-00-00
01-80-80-00-7F-0F-00-00
  GenericDesktopX: 127 -> 0

01-80-80-7F-7F-0F-00-00
01-80-80-FF-7F-0F-00-00
  GenericDesktopX: 127 -> 255

01-80-80-7F-7F-0F-00-00
01-80-80-7F-00-0F-00-00
  GenericDesktopY: 127 -> 0
  
01-80-80-7F-7F-0F-00-00
01-80-80-7F-FF-0F-00-00
  GenericDesktopY: 127 -> 255
※게임패드의 방향버튼은 기본이(버튼이 눌리지 않았을때) 127

01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-1F-00-00
  Button1: 0 -> 1

01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-2F-00-00
  Button2: 0 -> 1
  
01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-4F-00-00
  Button3: 0 -> 1

01-80-80-7F-7F-0F-00-00
01-80-80-7F-7F-8F-00-00
  Button4: 0 -> 1
※게임패드의 버튼은 기본이(버튼이 눌리지 않았을때) 0

 

※ HidSharp

 

반응형
Posted by J-sean
: