Microsoft Visual Studio 2015 – 윈도우 데스크톱 애플리케이션 개발용
프로젝트 소개
식물의 환경 조건을 실시간으로 파악하며 더 스마트하게 식물과 채소를 재배하세요. 아두이노 MKR1000만 있으면 충분합니다.
식물 생장에 필요한 환경 조건
식물 생장은 온도, 습도, 조도, 미네랄 영양분, 산소 등 여러 이상적인 환경 조건에 의존합니다.
온실에 적절한 양의 물을 공급하거나 적정 온도를 유지하는 것은 까다로운 과정이지만, 올바른 도구를 사용하면 훨씬 수월해집니다.
하드웨어 개요
온도/습도 측정
TH1 – 외부 온도: 방수 DS18B20 센서 – D1 핀 연결
TH2 – 내부 온도/습도: DHT22 센서 – D0 핀 연결
TH3 – 토양 상태: FS200/SHT25 센서 – SCL/SDA 핀(12/11번) 연결
수위 측정
W1 – 수위 측정용 초음파 센서 HC-SR04 사용. Echo 핀 A0, Trigger 핀 A1 연결. 이 값으로 4채널 릴레이(R1)를 통해 밸브 제어 가능.
공기 온도/산소 제어
A1 – 온도/습도 값을 기반으로 창문 개폐 시점 결정 – R2 릴레이 사용. 기후 조건에 맞춰 임계값 조정 필요.
릴레이 R1 / R2
창문 개폐, 펌프 구동 등 각종 제어 명령을 릴레이로 전송. R1은 디지털 핀 7,8,9,10에 연결, R2는 핀 5,6에 연결.
MKR1000 – aREST
모든 센서와 액추에이터를 연결한 후, aREST 라이브러리를 이용해 MKR1000에서 데이터를 수집하고 JSON 형식의 웹 인터페이스로 제공합니다. 제공된 라이브러리와 .ino 파일을 사용하고, 와이파이 라우터 설정에 맞게 수정하세요.
데이터 및 인터페이스
장치 인터페이스가 준비되면 로컬 네트워크에서 데이터를 수집해 시각화할 수 있습니다.
Visual Studio 2015와 .NET으로 윈도우 애플리케이션을 제작해 온실의 실시간 상태, 일일 히스토리, 각종 로그를 확인할 수 있습니다.
클라우드 저장은 DasData 온실 설정을 사용하거나 직접 데이터 채널을 생성하면 됩니다.
애플리케이션 폴더의 Settings.txt에서 DsKey와 AKey를 수정하세요. 정상 작동하면 데이터가 온라인에 나타납니다.
DasData의 해커스터 채널을 팔로우하면 향후 업데이트 소식을 받아볼 수 있습니다.
온실 자동화
온실 구성과 크기에 따라 어떤 밸브나 모터를 구동할지 결정하세요. 모든 제어는 릴레이를 통해 수행됩니다.
소스 코드
Filisera_Arduino (아두이노 스케치)
libraries.zip (필요 라이브러리 모음)
Filisera - vb.zip (Visual Basic 프로젝트)
Filisera - VS (Visual Studio 프로젝트)
Filisera_Arduino (C/C++)
아두이노/지누이노 MKR1000 보드용 aREST 라이브러리 사용
/* DASFilisera using aREST Library for the Arduino/Genuino MKR1000 board.
aREST - Written in 2016 by Marco Schwartz under a GPL license. */
// 필수 라이브러리 임포트
#include
#include
#include
#include "DHT.h"
#include
#include
#include
#include
// *************************
// ** 온도 센서들 **
// *************************
#define DHTPIN 0 // 내부 습도/온도/열지수
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
#define ONE_WIRE_BUS 1
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float umidSol = 0; // 토양 습도
float umidAer = 0; // 공기 습도
float tempIn = 0; // 실내 온도
float tempOut = 0; // 실외 온도
float tempSol = 0; // 토양 온도
float umidexIn = 0; // 체감 온도
// 수위 측정용 초음파 센서
#define echoPin A0 // Echo 핀 A0
#define trigPin A1 // Trigger 핀 A1
long duration; // 거리 계산을 위한 지속 시간
int HR_dist = 0; // 계산된 거리
int minimumRange = 5; // 최소 소나 범위
int maximumRange = 200; // 최대 소나 범위
unsigned long pulseduration = 0;
int nivelCm, nivelRamasCm;
int nivelProc, nivelVol;
int empty = 100;
int full = 100;
int sqrLevel, sqrInvertLevel;
// 와이파이 상태
int status = WL_IDLE_STATUS;
// aREST 인스턴스 생성
aREST rest = aREST();
// 와이파이 설정
char ssid[] = "WIFI_AP";
char password[] = "WIFI_PASSW";
// 수신 대기 TCP 포트
#define LISTEN_PORT 80
// 서버 인스턴스 생성
WiFiServer server(LISTEN_PORT);
// 센서 초기화
DHT dht(DHTPIN, DHTTYPE);
// 릴레이 핀
int aVentil, aLateral;
int inReleu1Ventil = 6;
int inReleu2Ventil = 7;
int inReleu3Ventil = 8;
int inReleu4Ventil = 9;
int inReleu1Lateral = 10;
int inReleu2Lateral = 11;
// API로 노출할 함수 선언
int ledControl(String command);
void setup(void) {
// 시리얼 시작
Serial.begin(115200);
// 변수 초기화 및 REST API 노출
// rest.variable("temperature", &temperature);
// rest.variable("humidity", &humidity);
// 함수 노출
rest.function("led", ledControl);
// 장치 이름과 ID 설정
rest.set_id("1");
rest.set_name("mkr1000");
// 와이파이 연결
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, password);
// 연결 대기 10초
delay(10000);
}
Serial.println("WiFi connected");
// 서버 시작
server.begin();
Serial.println("Server started");
// IP 주소 출력
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// DHT 초기화 - 내부
DHT dht(DHTPIN, DHTTYPE);
// sensors.begin(); // 외부 온도 센서 시작
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
// 변수 초기화 및 REST API 노출
rest.variable("Vol_container", &sqrLevel);
rest.variable("Umiditate_sol", &umidSol);
rest.variable("Umiditate_aer", &umidAer);
rest.variable("Temp_in", &tempIn);
rest.variable("Temp_out", &tempOut);
rest.variable("Temp_sol", &tempSol);
// rest.variable("Umidex_in", &umidexIn);
// sensors.requestTemperatures(); // 외부 온도 요청
}
void loop() {
getmyDistance(); // 거리 측정
// getSoilVals(); // 토양 값 읽기 (주석 처리됨)
getInsideVals(); // 실내 값 읽기
// getOutSideVals(); // 실외 값 읽기 (주석 처리됨)
// REST 호출 처리
WiFiClient client = server.available();
if (!client) {
return;
}
while (!client.available()) {
delay(1);
}
rest.handle(client);
}
void getmyDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
// 거리 계산
HR_dist = duration / 58.2;
// sqrLevel = empty - HR_dist;
if (HR_dist >= maximumRange || HR_dist <= minimumRange) {
sqrLevel = 0;
} else {
sqrLevel = empty - HR_dist;
Serial.println(HR_dist);
}
delay(100);
}
void getDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(10);
// 10µs 펄스 전송으로 Ping 활성화
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// 수신 펄스 길이 측정
pulseduration = pulseIn(echoPin, HIGH);
// 펄스 길이의 절반
pulseduration = pulseduration / 2;
// 센티미터로 변환
nivelRamasCm = int(pulseduration / 29);
nivelCm = empty - nivelRamasCm;
nivelVol = map(nivelRamasCm, full, empty, 100, 0);
// 센티미터 단위 수위 출력
if (nivelCm >= -5 && nivelCm <= 135) {
double a = nivelCm / 100 * nivelVol;
int sqrLevel = 240 - nivelCm;
int sqrInvertLevel = 120 + nivelRamasCm;
if (nivelCm > 65 && nivelCm <= 85) {
}
if (nivelCm > 85 && nivelCm <= 100) {
}
}
}
long microsecondsToCentimeters(long microseconds) {
// 음속 340m/s = 29µs/cm
// 왕복 거리이므로 절반으로 나눔
return microseconds / 29 / 2;
}
void getInsideVals() {
float h = dht.readHumidity(); // 습도 읽기
float t = dht.readTemperature(); // 섭씨 온도 읽기
// float f = dht.readTemperature(true); // 화씨 온도 읽기
umidAer = h;
tempIn = t;
// 읽기 실패 시 조기 리턴
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// 화씨 열지수 계산 (기본값)
// float hif = dht.computeHeatIndex(f, h);
// 섭씨 열지수 계산 (isFahreheit = false)
// float hic = dht.computeHeatIndex(t, h, false);
// umidexIn = hic;
}
void getOutSideVals() {
tempOut = sensors.getTempCByIndex(0);
Serial.println("Temperature Out: ");
Serial.print(tempOut);
}
void getSoilVals() {
umidSol = SHT2x.GetHumidity();
tempSol = SHT2x.GetTemperature();
Serial.println("Humidity Soil(%RH): ");
Serial.print(umidSol);
Serial.print(" Temperature Soil (C): ");
Serial.print(tempSol);
}
// sensors.requestTemperatures(); // 외부 온도 요청
// API로 접근 가능한 커스텀 함수
int ledControl(String command) {
// 명령에서 상태 가져오기
int state = command.toInt();
digitalWrite(6, state);
return 1;
}
libraries.zip (C/C++)
Filisera에서 사용된 라이브러리 모음 (다운로드만 가능)
Filisera - vb.zip (VBScript)
.NET Visual Studio 프로젝트 (다운로드만 가능)
Filisera - VS (VBScript)
아두이노에서 데이터를 읽어 인터페이스를 표시하는 .NET 파일
Imports System.Globalization
Imports System.IO
Imports System.Net
Imports System.Threading
Imports System.Windows.Forms.DataVisualization.Charting
Imports Newtonsoft.Json
Public Class Form1
Private _deviceIP As String = "" ' 장치 IP
Private intVolumContainer, intUmidSol, intUmidSera, intTempAfara, intTempSera, intTempSol, intUmidex As String ' 변수들
Private strR1, strR2 As String ' 릴레이
Public Count As CountDown ' 카운트다운 타이머
Private _dasResult As String = "" ' 장치 센서 읽기 결과
Private _AKey As String = "" ' DasData 사용자 키
Private _DSKey As String = "" ' DasData 데이터셋 키
Private _myDas As New dasData.das
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Count = New CountDown(50, 0) ' 5초 업데이트 주기
AddHandler Count.Tick, AddressOf Count_Tick
AddHandler Count.TimesOut, AddressOf Times_up
Try
' Settings.txt에서 설정 읽기
Dim path As String = Directory.GetCurrentDirectory()
Dim FILE_NAME As String = path & "\Settings.txt"
Dim myText As String = ""
If System.IO.File.Exists(FILE_NAME) = True Then
Dim objReader As New System.IO.StreamReader(FILE_NAME, System.Text.Encoding.Default)
Do While objReader.Peek() <> -1
myText &= objReader.ReadLine()
Loop
Dim _settingItems() As String = myText.Split(" ")
_deviceIP = _settingItems(0) ' 장치 IP
_AKey = _settingItems(1).Replace("akey:", "")
_DSKey = _settingItems(2).Replace("dskey:", "")
cbxEnabled.Text = "Device: " & _deviceIP
txtInfo.Text = "IP device: " & _deviceIP & vbNewLine & "AKey: " & _AKey & vbNewLine & "DSKey: " & _DSKey & vbNewLine
strR1 = _settingItems(3).Replace("relay1:", "")
txtInfo.Text += "Relay1: " & strR1 & vbNewLine
strR2 = _settingItems(4).Replace("relay2:", "")
txtInfo.Text += "Relay2: " & strR2 & vbNewLine
objReader.Dispose()
objReader.Close()
End If
Catch ex As Exception
lblDevice.Text = ex.Message.ToString
End Try
cmdCheckDevice() ' 로컬 설정
Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
' Thread.CurrentThread.CurrentUICulture = New CultureInfo("ro-RO")
cmdStartFilisera()
End Sub
Private Sub Count_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
cmdGetSensorValues()
cmdTriggers()
If CDate(dtFrom.Text).ToString("dd.MM.yyyy") = Date.Now().ToString("dd.MM.yyyy") Then
cmdStartFilisera()
End If
End Sub
Private Sub Times_up(ByVal sender As System.Object, ByVal e As System.EventArgs)
' Count.Reset()
' Count.Pause()
End Sub
Private Sub cmdStartFilisera()
Try
dtFrom.MaxDate = DateTime.Now
_dasResult = _myDas.getDas(_DSKey, "json", 0, 100)
cmdFillData()
Catch ex As Exception
lblDevice.Text += ex.Message.ToString
End Try
End Sub
Private Sub cbxEnabled_CheckedChanged(sender As Object, e As EventArgs) Handles cbxEnabled.CheckedChanged
cmdCheckDevice()
End Sub
Private Sub cmdCheckDevice()
Try
If cbxDemo.Checked = False Then
lblDevice.Text = ("Enable device!")
lblEvenimente.Text = Date.Now.ToString("dd.MM.yyyy HH:mm:ss")
If cbxEnabled.Checked = True Then
Dim pingsender As New Net.NetworkInformation.Ping
If Not pingsender.Send(_deviceIP).Status = Net.NetworkInformation.IPStatus.Success Then
lblDevice.Text = ("Device not availble on the local network!")
cbxEnabled.Checked = False
btnTemperatura.Enabled = False
btnVolumContainer.Enabled = False
Count.Reset()
Count.Pause()
MessageBox.Show("Device at " & _deviceIP & " not found!")
Else
lblDevice.Text = ("Device connected!")
btnTemperatura.Enabled = True
btnVolumContainer.Enabled = True
cmdGetSensorValues()
Timer1.Enabled = True
cmdAddData()
Count.Start()
End If
Else
End If
Else
btnTemperatura.Enabled = True
btnVolumContainer.Enabled = True
cmdGetSensorValues()
Timer1.Enabled = True
cmdAddData()
Count.Start()
End If
Catch ex As Exception
End Try
End Sub
Private Sub btnVolumContainer_Click(sender As Object, e As EventArgs) Handles btnVolumContainer.Click
' https://192.168.0.102/digital/7/1
' 버튼으로 물 차단
Dim _ItemsR1() As String = strR1.Split(",")
If btnVolumContainer.Text.Contains("Open") Then
cmdRelay(_ItemsR1(0), 1)
cmdRelay(_ItemsR1(1), 1)
cmdRelay(_ItemsR1(2), 0)
cmdRelay(_ItemsR1(3), 0)
btnVolumContainer.Text = "Close water"
Else
cmdRelay(_ItemsR1(0), 0)
cmdRelay(_ItemsR1(1), 0)
cmdRelay(_ItemsR1(2), 1)
cmdRelay(_ItemsR1(3), 1)
btnVolumContainer.Text = "Open water"
End If
End Sub
Private Sub btnTemperatura_Click(sender As Object, e As EventArgs) Handles btnTemperatura.Click
' 버튼으로 창문 차단
Dim _ItemsR2() As String = strR2.Split(",")
If btnTemperatura.Text.Contains("Open") Then
cmdRelay(_ItemsR2(0), 1)
cmdRelay(_ItemsR2(1), 1)
btnTemperatura.Text = "Close window"
Else
cmdRelay(_ItemsR2(0), 0)
cmdRelay(_ItemsR2(1), 0)
btnTemperatura.Text = "Open window"
End If
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
cmdAddData()
End Sub
Private Sub btnTestCloud_Click(sender As Object, e As EventArgs) Handles btnTestCloud.Click
Try
cmdStartFilisera()
Catch ex As Exception
MessageBox.Show("Lost connection with DasData!")
End Try
End Sub
Private Function cmdRelay(ByVal _DPin As String, ByVal _cmd As Int16)
Try
Dim _urlCommand As String = _deviceIP & "/digital/" & _DPin & "/" & _cmd
Dim client As New WebClient()
client.Headers.Add("user-agent", "Arduino/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)")
Dim data As Stream = client.OpenRead(_urlCommand)
Dim reader As New StreamReader(data)
Dim s As String = reader.ReadToEnd()
' txtInfo.Text += (s)
data.Close()
reader.Close()
Catch ex As Exception
End Try
End Function
Private Sub dtFrom_ValueChanged(sender As Object, e As EventArgs) Handles dtFrom.ValueChanged
Try
' 날짜 선택 기반 데이터 조회
_dasResult = _myDas.getDas(_DSKey, "jsond", CDate(dtFrom.Text).ToString("dd.MM.yyyy"), CDate(dtFrom.Text).ToString("dd.MM.yyyy"))
cmdFillData()
Catch ex As Exception
MessageBox.Show(ex.Message.ToString)
End Try
End Sub
Private Sub cmdGetSensorValues()
Try
' 장치에서 센서 값 읽기
If cbxDemo.Checked = False Then
Dim client As New WebClient()
client.Headers.Add("user-agent", "Arduino/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)")
Dim data As Stream = client.OpenRead("https://" & _deviceIP & "/index.html")
Dim reader As New StreamReader(data)
Dim s As String = reader.ReadToEnd()
s = s.Replace("""", "").Replace("}", "").Replace("{", "").Replace(" ", "").Replace("variables:", "")
Dim sItems() As String = s.Split(",")
intVolumContainer = cmdGetVal(sItems(0))
intUmidSol = cmdGetVal(sItems(1))
intUmidSera = cmdGetVal(sItems(2))
intTempSera = cmdGetVal(sItems(3))
intTempAfara = cmdGetVal(sItems(4))
intTempSol = cmdGetVal(sItems(5))
data.Close()
reader.Close()
Else
intVolumContainer = _rnd(60)
intUmidSol = _rnd(80)
intUmidSera = _rnd(20)
intTempSera = _rnd(45)
intTempAfara = _rnd(57)
intTempSol = _rnd(66)
End If
ggVolum.Value = intVolumContainer
rgVolum.Value = intVolumContainer
ggUmidSol.Value = intUmidSol
ggUmidSera.Value = intUmidSera
ggTempSera.Value = intTempSera
ggTempOut.Value = intTempAfara
ggTempSol.Value = intTempSol
Catch ex As Exception
' {"variables" {"Volum_container": 0, "Umiditate_sol": 0.00, "Umiditate_aer": 36.60, "Temp_in": 26.50, "Temp_out": 0.00, "Temp_sol": 0.00, "Umidex_in": 26.37}, "id": "1", "name": "FiliSera", "hardware": "arduino", "connected": true}
End Try
End Sub
Private Function cmdGetVal(ByVal _sItem As String)
Try
' 문자열 분할 후 값 추출
Dim _s() As String = _sItem.Split(":")
Return _s(1)
Catch ex As Exception
End Try
End Function
Private Sub cmdAddData()
Try
' DasData 클라우드 스토리지로 데이터 전송
Dim _strFiliseraDataSend As String = intVolumContainer & "|" & intUmidSol & "|" & intUmidSera & "|" & intTempAfara & "|" & intTempSera & "|" & intTempSol
'& "|" & intUmidex & "|"
Dim _dasResult As String = _myDas.sendDas(_strFiliseraDataSend, _DSKey, _AKey)
Catch ex As Exception
cmdLogMe("ERROR..." & ex.Message.ToString(), "error")
End Try
End Sub
Private Sub cmdFillData()
Try
' 인터페이스에 모든 데이터 채우기
Dim dataSet As DataSet = JsonConvert.DeserializeObject(Of DataSet)(_dasResult)
Dim dataTable As DataTable = dataSet.Tables(0)
' 그리드뷰
DataGridView1.DataSource = dataSet.Tables(0)
DataGridView1.AutoGenerateColumns = True
' 차트
ChartTemp.DataSource = dataTable
ChartTemp.Series.Clear()
chartUmid.DataSource = dataTable
chartUmid.Series.Clear()
chartVolum.DataSource = dataTable
chartVolum.Series.Clear()
Dim i As Integer = 0
Dim j As Integer = 0
Dim k As Integer = 0
For Each table In dataSet.Tables
For Each row In table.Rows
For Each col In table.Columns
Dim colName As String = col.ColumnName.ToString
If colName <> "id" And colName <> "AIDate" Then
Try
Dim serieName As String = RTrim(colName)
' 수위
If colName.Contains("Nivel") Then
chartVolum.Series.Add(serieName)
chartVolum.Series(serieName).LabelFormat = "N1"
chartVolum.Series(i).ChartType = SeriesChartType.Line
chartVolum.Series(i).BorderWidth = 2
chartVolum.Series(i).BorderDashStyle = ChartDashStyle.Solid
chartVolum.Series(serieName).YValueMembers = RTrim(colName)
chartVolum.Series(serieName).XValueMember = "AIDate"
i += 1
End If
' 습도
If colName.Contains("Umid") Then
chartUmid.Series.Add(serieName)
chartUmid.Series(serieName).LabelFormat = "N1"
chartUmid.Series(j).ChartType = SeriesChartType.Line
chartUmid.Series(j).BorderWidth = 2
chartUmid.Series(j).BorderDashStyle = ChartDashStyle.Solid
chartUmid.Series(serieName).YValueMembers = RTrim(colName)
chartUmid.Series(serieName).XValueMember = "AIDate"
j += 1
End If
' 온도
If colName.Contains("Temp") Then
ChartTemp.Series.Add(serieName)
ChartTemp.Series(serieName).LabelFormat = "N1"
ChartTemp.Series(k).ChartType = SeriesChartType.Line
ChartTemp.Series(k).BorderWidth = 2
ChartTemp.Series(k).BorderDashStyle = ChartDashStyle.Solid
ChartTemp.Series(serieName).YValueMembers = RTrim(colName)
ChartTemp.Series(serieName).XValueMember = "AIDate"
k += 1
End If
Catch ex As Exception
End Try
End If
Next
Exit For
Next
Next
' 차트 데이터 바인딩
ChartTemp.DataBind()
ChartTemp.Visible = True
chartUmid.DataBind()
chartUmid.Visible = True
chartVolum.DataBind()
chartVolum.Visible = True
Catch ex As Exception
cmdLogMe("ERROR..." & ex.Message.ToString(), "error")
End Try
End Sub
Private Sub cmdTriggers()
' 트리거 설정 및 로그 저장
Select Case intVolumContainer
Case > 80
cmdLogMe("HIGH HIGH - Container volume - stop water", "0")
Case > 70
' cmdLogMe("HIGH - Container volume - water will start", "1")
Case < 20
' cmdLogMe("LOW - Container volume low - water will stop", "1")
Case < 10
cmdLogMe("LOW LOW - Container volume high high high - start water", "0")
End Select
Select Case intTempSera
Case > 38
cmdLogMe("HIGH HIGH - Temperature in green house - open windows", "0")
Case > 30
' cmdLogMe("HIGH - Temperature in green house - prepare windows", "1")
Case < 10
' cmdLogMe("LOW - Temperature in green house - prepare windows", "1")
Case < 10
cmdLogMe("LOW LOW - Container volume high high high - start water", "0")
End Select
End Sub
Public Function _rnd(ByVal n As Integer) As Integer
' 난수 생성기 초기화
Dim r As New Random(System.DateTime.Now.Millisecond)
Return r.Next(1, n)
End Function
Private Sub cmdLogMe(message As String, _type As String)
Try
Dim _strLog As String = "adeewdf4-4aa34-14ass24-8436-aea1" ' 로그용 DasData DS 키
lstEvenimente.Items.Add((System.DateTime.Now & " " & message) + Constants.vbNewLine)
' DasData에 로그 저장
_myDas.sendDas(message & "|" & _type, _strLog, _AKey)
Catch ex As Exception
cmdLogMe("ERROR..." & ex.Message.ToString(), "error")
End Try
End Sub
End Class