2021. november 30., kedd

USB-RS232 Csatoló

 

A műszervezérlés tervem megvalósításaként, először megterveztem az USB-RS232 csatolómat. Lehet, hogy ez még nem az utolsó verziója, de egyenlőre végeztem a tervezési fázissal.

A szerkezet a CH340G chipen alapul, amit korábban az ESP8266-os programozómon is sikeresen használtam, ugyanez van egy rakás kínai USB-Soros kábelben, Arduino-kban, 3D nyomtató vezérlőkben. Sosem volt semmi bajom ezekkel az eszközökkel. A megfelelő jelszintek előállítására hozzáadtam még egy MAX232-es tokot.

Valószínüleg ez a megoldás nem optimális, miután nincs meg rajta az összes RS232 jel, de azt hiszem, egyenlőre jó lesz így (nem igazán akarok most több energiát belerakni ebbe).

A kapcsolási rajz:


A nyák terv:


Esetleg észreveheted a kapcsolási rajzon és a nyák terven, hogy "kettős" USB csatlakozás van rajta. Ez azt jelenti, hogy az USB jelek mind egy mikro USB csatlakozón, mind pár forszemen elérhetőek. Ez a megoldás azt a lehetőséget kínálja, hogy akár USB csatlakozóval, akár kábellel szereljük össze az eszközt.
Ennek a koncepciónak megfelelően két különböző dobozkát terveztem hozzá.
USB csatlakozóhoz:


Kábelhez:


Megfigyelhető, hogy a panel maga a 3D terven szürke. Az ok, hogy nem tudtam a színes 3D modellt beimportálni az OpenSCAD-be, amit a 3D modellezéshez használok (lehet, nem is tud ilyet).
Az eredeti 3D nézet, ilyen:


Jelenleg még nem akarom a panelt legyártani, mert a GPIB csatoló következő verzióján dolgozom és össze akarom montírozni egy panelre a gyártási költségek csökkentése miatt.

A tervek itt találhatóak:

Nekiálltam a mindenféle műszervezérlős dolgom átszervezésének is. A kapcsolódó repók itt lesznek majd elérhetőek:


2021. november 27., szombat

Műszervezérlés - újrakezdve

 

Bevezető

Az elmúlt években rengeteg munkát raktam a különböző műszereim számítógépes vezérlésébe. A terv az volt, hogy valami hozzáadott értéket teremtsek vele, úgy mint logolás, jobb láthatóság, több - integrált - funkció, stb.
Úgy néz ki, hogy ezzel kicsit megbuktam, miután semmi sem jutott el, a használhatósági állapotba.
Az egészet, hónapokkal ezelőtt félretettem. Most úgy érzem, ideje leporolnom és újrakezdenem, hogy valami "működő" állapotig eljussak vele.

Tervek

A forrás repók újraszervezése

Ez azért szükséges, mert rengeteg dolgot tanultam az elmúlt években a munkám kapcsán a gitről (branch stratégiák, release kezelés, etc.)

USB-RS232 interfész tervezés

Van egy pár eszközöm ami RS232 interfésszel rendelkezik a GPIB helyett/mellett. Igen, vehetsz USB-Soros átalakítót gombokért. Miért kell egy másik? A legtöbb darab amit kapsz, nem tudja a megfelelő jelszinteket. TTL szintet használnak RS232 helyett. A legtöbb professzionális műszernek szüksége van a megfelelő jelszintekre. A megfelelő csatoló nem olcsó, vagy azt kockáztatod, hogy veszel valami vackot az Aliexpressen ami azt állítja magáról, hogy megfelelő, közben nem.

USB-GPIB hardver újratervezése

Az ATMEGA32U4 alapú interfészem tökéletesem működik. Az elmúlt években ugyanakkor kiderült pár dolog ami arra késztet, hogy szükség van pár módosításra:
  • Olyan fizikai terv kialakítása, hogy 3D nyomtatott dobozba lehessen tenni.
  • Elhagyni azokat a csatlakozókat amiket későbbi továbbfejlesztésre terveztem bele mint kijelző plusz eszközök vezérlése, stb.
  • Soros debug lehetőség (az AR488-nak megfelelően)
  • Az Arduino Leonardo bootloaderrel való kompatibilitás
  • Megtartani a teljes 8bites buszból adódó adat transzfer előnyöket (módosított bootloader szükséges)
  • Az AR488 szoftverrel való kompatibilitás megtartása (https://github.com/Twilight-Logic/AR488)
  • Aktivitás LED-ek hozzáadása (az eredeti Arduino Leonardo-nak megfelelően)
  • Teljes GPIB meghajtó TI ICkkel (másik hardver verzió szükséges)
Az AR488 kompatibilitás megtartása nem jelenti azt, hogy a saját firmware-emet ki tervezném dobni. Változatlanul nem békéltem megy a 3000+ sor kóddal egyetlen forrásfájlban. Az AR488 még mindíg nem támogatja a GPIB másodlagos címzést. Van egy rakás eszközöm (VXI keretek, moduláris labortáp keret), amiknek szüksége van erre. A másik oldalon támogatja a device üzemmódot, a TI GPIB IC-it, amik az enyémből hiányoznak, továbbá megvan a szoftver támogatása olyan eszközökben mint a sigrok.

Proper bootloader for USB-GPIB

Csináltam egy bootloadert a v2.0-ás panelhez. Ez egy annak a mellényúlásnak az eredménye volt, hogy újrahasznosítottam az Arduino Leonardo USB visszajelző LEDjeit, ami megölte a GPIB kommunikációt. A problémát akkor megoldottam, de az eredménye egy rosszul dokumentált (https://it-pro-hu.blogspot.com/2020/04/gp-ib-5-v20-panel.html), nehezen reprodukálható állapot lett. Ráadásul ez kinyírja a LED-eket és nem áthelyezi más uC lábakra. Most létre akarok hozni egy karbantartható, újrafordítható, megfelelően telepíthető megoldást. Ezen túl szeretnék a szabályoknak megfelelő PID/VID páros kérni a pid.codes-tól.

Tápegység vezérlő szoftver

A virtuális műszer szoftverem sok dologra lenne alkalmas, de rájöttem, hogy túl magasra tettem a lécet, első nekifutásra. Sok mindent megcsináltam már benne, a jelenlegi újrakezdéshez kisebbet akarok fogni.
Tehát megtartva a cserélhető driver támogatást akarok csinálni egy tápegység vezérlő szoftvert a rengeteg tápegységemhez (ráadásul a HP 66000A moduláris tápegység nem is használható szoftver nélkül, mert nincs hozzá meg a saját billentyűzete). Ebbe egyenlőre nem akarom magasabb szintű funkciókat rakni.

Továbbiak...

Természetesen, nem akarok itt megállni, újra akarom indítani a virtuális műszer fejlesztésem, a karakterisztika rajzolót, stb.
Ezek a dolgok egyenlőre homályosak, és ha elveszítem a fókuszt ezem megint, annak csak egy polcra rakott project hegy lesz az eredménye. Megint.

2021. november 11., csütörtök

Terraform, Cloudformation és Cognito

Némi IT és némi felhő újra

IaC eszközökkel dolgozom már nem is igazán tudom mióta. Az AWS CloudFormation-nel kezdtem valamikor 2014 körül (nem biztos, ez a ködös múltba vész)


Amikor elkezdtem a Terraformról tanulni, bennem volt a félelem, hogy nem fogok teljes AWS funkcionalitást kapni. A CloudFormation natív AWS eszköz. Valami amit egy külső gyártó fejleszt - elméletben - csak követheti a szolgáltató natív eszközét.

Elkezdtem Terraformot használni, mert ez volt az ügyfél elvárása, tehát a váltás nem az én döntésem volt. A fenti félelmem akkor vált kicsit valósággá amikor az ügyfél nem követte az AWS Provider verzióit megfelelően a saját deployment agent-jein (tehát ez nem róható fel sem a HashiCorpnak, sem a Terraform közösségnek). Tehát tulajdonképpen nem látszott valós lemaradás a Terraform oldalán. Emellett Terraform kódot írni sokkal kényelmesebb, sokkal több lehetőséget nyújt amikor feldolgozni, konvertálni kell, a rendelkezésre álló információt.

Egy pár hete, kb. három év kizárólagos Terraform munka után belecsöppentem újra egy CloudFormation projectbe.

Van egy - azt hittem - szuper egyszerű feladat. Publikálni egy Cognito User Pool Client titkos kulcsot az SSM Parameter Store-ba, titkosítva.

Terraformban ez így néz ki:

// Create Cognito User Pool
resource "aws_cognito_user_pool" "pool" {
  name = "pool"
}

// Create Cognito User Pool Client
resource "aws_cognito_user_pool_client" "client" {
  name = "client"
  user_pool_id = aws_cognito_user_pool.pool.id
  generate_secret     = true
}

// Publish to SSM Parameter Store
resource "aws_ssm_parameter" "secret" {
  name        = "/production/cognito/clientSecret"
  type        = "SecureString"
  value       = ${aws_cognito_user_pool_client.client.client_secret}
}

És kész is vagyunk.

Próbáljuk meg ugyanezt a CloudFormation-ben.

Vajon a AWS::Cognito::UserPoolClient objektum, ki tudja-e exportálni a titkos kulcsot? Nem. Forrás: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-userpoolclient.html

Vajon a AWS::SSM::Parameter objektum tud-e SecureString értéket létrehozni? Nem. Forrás: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-parameter.html

Itt van ahol a fenti teóriám "A CloudFormation-nek előrébb kell járnia mint a Terraformnak" megbukik.

Sok mindennel próbálkoztam sikertelenül, hogy megoldjam ezt. Végülis a következő kódrészlet működött (egy megjegyzés: a Python kódban, az import cfnresponse nem az én trehányságom miatt van külön sorban. Ez kell az AWS lambdának, hogy észrevegye, kell neki a cfnresponse.py és belerakja a deployment során a zip fájlba, ugyanis nem része a pip repónak):

Resources:
  # Create Cognito User Pool
  UserPool:
    Type: "AWS::Cognito::UserPool"
    Properties:
      UserPoolName: pool

  # Create Cognito User Pool Client
  UserPoolClient:
    Type: "AWS::Cognito::UserPoolClient"
    Properties:
      AccessTokenValidity: 15
      AllowedOAuthFlowsUserPoolClient: false
      ClientName: client
      GenerateSecret: true

  # You need a lambda to
  #     - read from the cognito user pool client
  #     - write to the parameter store
  #     - report back to the CloudFormation when finished
  CognitoSecretExporterLambda:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: CognitoSecretExporter
      Runtime: python3.9
      Role: !GetAtt CognitoSecretExporterExecutionRole.Arn
      Handler: index.handler
      Timeout: 30
      Environment:
        Variables:
          CognitoUserPoolId: !Ref UserPool
          CognitoUserPoolClientId: !Ref UserPoolClient
          ssmParameterName: /production/cognito/ClientSecret
      Code:
        ZipFile: |
          import boto3, os
          import cfnresponse

          def handler(event, context):
              CognitoUserPoolId = os.environ['CognitoUserPoolId']
              CognitoUserPoolClientId = os.environ['CognitoUserPoolClientId']
              ssmParameterName = os.environ['ssmParameterName']

              # Read Cognito
              cognito = boto3.client('cognito-idp')
              response = cognito.describe_user_pool_client(
                  UserPoolId = CognitoUserPoolId,
                  ClientId = CognitoUserPoolClientId
              )
              cognitoClientSecret = response['UserPoolClient']['ClientSecret']
              print(cognitoClientSecret)
              ssm = boto3.client('ssm')

              # Write to parameter store
              response = ssm.put_parameter(
                  Name = ssmParameterName,
                  Description = '[CF] Cognito Client Secret used by the WebApp',
                  Value = cognitoClientSecret,
                  Type = 'SecureString',
                  KeyId = 'alias/aws/ssm',
                  Overwrite = True,
                  Tier='Standard'
              )

              # Report success to CloudFormation
              responseData = {}
              responseData['Data'] = 120
              cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData) 

  # Trigger the lambda from the CloudFormation stack
  CognitoSecretExporterInvoke:
    Type: AWS::CloudFormation::CustomResource
    DependsOn: CognitoSecretExporterLambda
    Version: "1.0"
    Properties:
      ServiceToken: !GetAtt CognitoSecretExporterLambda.Arn 

  # IAM Role for the lambda above
  CognitoSecretExporterExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: CognitoSecretExporterExecutionRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
              - lambda.amazonaws.com
          Action:
            - sts:AssumeRole
      Path: "/"
      Policies:
      - PolicyName: root
      PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Sid: EnablePutLogEvents
              Effect: Allow
              Action:
                - logs:CreateLogGroup
                - logs:CreateLogStream
                - logs:PutLogEvents
              Resource:
                - '*'
            - Sid: ReadCognito
              Effect: Allow
              Action:
                - cognito-idp:DescribeUserPoolClient
              Resource:
                - !GetAtt UserPool.Arn
            - Sid: ParamStore
              Effect: Allow
              Action:
                - ssm:DeleteParameter
                - ssm:PutParameter
                - ssm:GetParameter
              Resource: 
                - !Sub arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/production/cognito/ClientSecret