[개발 일지] SNET ECAT Configurator 3

타키탸키·2023년 2월 24일
0

개발 일지

목록 보기
11/11

01.25

  • EcatAxisList struct 메서드 로직 구현
    • Clear 메서드에 maps 패키지 활용
      • Go의 map에는 모든 key-value를 한꺼번에 삭제할 수 있는 Clear 기능이 없다
      • 따라서, map을 순회하며 하나씩 삭제해야 한다
      • maps 패키지의 Clear 메서드를 활용하면 한꺼번에 map의 원소를 삭제할 수 있다
    • EcatEsi의 reload 메서드 수정
      • ioutil 패키지가 deprecated됨에 따라 Esi path를 직접 열고 esi 파일을 읽을 수 있도록 수정했다(path.ReadDir)
    • 에러 코드
      • 에러 코드가 필요없는 SetClear는 리턴 타입 제외
      • Delete 메서드에 found flag를 추가하여 값이 없을 경우에는 에러를 반환하도록 수정
    • ScanRoutine 메서드 이름 수정
      • Go에서는 함수명의 대소문자 구분을 하므로 scan으로 변경
  • EcatManager struct에 SetupAutoAxes 메서드 추가
    • EcatAxisList의 axes map에 연결 순서대로 slave axis를 자동으로 추가해주는 기능
    • slave의 축이 두 개인 경우, channel index를 활용하여 channel 순서까지 고려하도록 로직 구현
    • scan의 마무리 단계에서 호출

01.26

  • reciever 이름 단순화
    • 직관성과 Go convention 고려
      • ex:) EcatDevice: ed -> d
      • ex:) EcatManager: em -> m

01.27

  • bytes to struct 코드 변경
    • byte 코드로 넘어온 node 데이터를 EcatNode에 매핑하기 위한 형변환 코드 수정
    • 일반적으로는 encoding/json 패키지의 Unmarshal 함수를 통해 JSON 데이터를 파싱한다
    • 그러나, c++로 작성된 Runtime 데이터는 JSON이 아닌 byte 배열로 전송된다
    • 따라서, 메모리 블록의 주소를 직접 가져와 해당 데이터 유형의 포인터로 변환하여 라이브러리 함수로 전달해야 한다

Golang cast memory to struct

nodeBuf := (*(*[1<<31 - 1]byte)(unsafe.Pointer(&en)))[:unsafe.Sizeof(EcatNode{})]

1. en
- 'EcatNode' 타입의 변수
- 메모리에 할당된 구조체의 주소 값을 가지고 있다

2. unsafe.Pointer(&en)
- en 변수의 주소값을 가리키는 포인터 역할
- Go 언어에서 포인터 연산을 지원하지 않는 불안전한 타입(unsafe)이므로 사용에 주의
- 메모리 누수 혹은 예기치 않은 동작을 야기할 수 있다

3. (*(*[1<<31 - 1]byte)(unsafe.Pointer(&en)))
- `unsafe.Pointer`를 `[]byte` 타입으로 형변환 후, 주소값을 가지고 있는 바이트 배열 생성
- `1<<31 - 1': 배열 크기, Go 언어에서 배열의 최대 크기로 제한되어 있는 값

4. [:unsafe.Sizeof(EcatNode{})]
- EcatNode 구조체 크기만큼의 바이트 슬라이스 생성
- 3에서 생성된 바이트 배열에서 EcatNode 크기만큼 자른 결과
- 생성된 슬라이스를 nodeBuf 변수에 할당

** 요약 **
- `en` 변수가 가리키는 EcatNode 구조체의 메모리를 바이트 슬라이스로 변환하는 코드

02.01

  • 변수명 변경
    • 약어 사용을 지양하고 정확한 표현으로 변경
      • ex:) en => EcatNode
      • ex:) ecInfo => EtherCATInfo
    • 모호한 표현 지양
      • ex:) index => deviceIndex
    • 이러한 표기는 Go convention에는 어긋나지만 협업을 위해 필요
  • 중복된 Redis Dial 코드 제거
    • redis dial 관련 코드를 RedisMessageBroker의 Initialize 메서드 안으로 옮김
      • 기존에는 RedisMessageBroker의 모든 메서드에 dial 함수가 포함되어 있었다
      • 매번 Dial을 호출하면 DB Connection에 대한 동시성 문제가 발생한다
      • Initialize 메서드 호출 시에 딱 한 번 Dial을 호출하고 해당 Connection 하나만을 사용하도록 코드 변경
      • 모든 메서드에 Close 메서드를 지연하는 코드를 추가하여 Connection 유지

02.02

  • RedisMessageBroker의 멤버 변경
    • 기존에는 network와 ip를 멤버로 가지고 Initialize 함수에서 초기화
    • network와 ip는 Initalize 함수에서만 사용되므로 멤버에서 제외
    • address 변수를 선언하여 ip와 redis port 번호인 ":6379"를 concat하여 할당
    • device를 멤버를 추가하여 외부로부터 값을 직접 입력 받을 수 있도록 변경
      • 기존에는 device1으로 하드코딩 됨
  • log.Fatalln 코드 대체
    • Fatalln 함수는 로그를 출력하고 프로그램을 강제 종료시킨다
    • 따라서, 에러가 발생하면 프로그램이 강제 종료되므로 더 진행시킬 수 없다
    • log.Println으로 에러 출력만 하도록 코드 변경
  • RedisMessageBroker의 ReadSend에 mutex 추가
    • 서로 다른 goroutine에서 Connection에 동시 접근하는 것을 방지하기 위해 mutex 추가
  • EcatConnection struct 추가
    • EcatManager로부터 RuntimeConnection 분리
      • RuntimeConnection에 직접 접근하지 않고 EcatConnection을 통해 간접 접근
      • ehtercat 영역의 EcatManager에서 runtime 영역의 RuntimeConnection에 직접 접근하지 않고 중간 계층을 두어 시스템 영역과 애플리케이션 영역 분리
    • ScanScanResult 메서드 추가
      • EcatManager의 scan 메서드 내부에 있던 메세지 전송 로직을 함수화하여 분리
profile
There's Only One Thing To Do: Learn All We Can

0개의 댓글