Thursday, October 16, 2025

AWS CDK Set Parameter Store Value

Problem:

There are multiple ways to set a parameter store value. Which one should I use?

Solution:

1. Set parameter at deploy time:

Use this pattern when you want to create or update a plain-text SSM parameter during deployment. Creates an AWS::SSM::Parameter resource that resolves at deploy time.

new ssm.StringParameter(this, 'Param', {
  parameterName: '/my/plain/parameter',
  stringValue: 'my-value',
});

2.   Set parameter with a JSON value:

Use when you need to store structured data (e.g., configuration or mapping) as a JSON string.
The object is serialized with JSON.stringify() before being written to SSM.

new ssm.StringParameter(this, 'JsonParam', {
  parameterName: '/app/config',
  stringValue: JSON.stringify({
    apiUrl: 'https://api.example.com',
    featureFlags: { enableNewUI: true, betaAccess: false },
  }),
});

To read it back, retrieve the value and parse it:.

const config = JSON.parse(ssm.StringParameter
  .fromStringParameterAttributes(this, 'JsonParamRef', {
    parameterName: '/app/config',
  })
  .stringValue);

3.  Set parameter with a lazy value:

Use when the parameter value depends on another construct (e.g., a pipeline name) and must be evaluated dynamically at synth. cdk.Lazy defers the value computation until synthesis.

new ssm.StringParameter(this, 'LazyParam', {
  parameterName: '/pipeline/name',
  stringValue: cdk.Lazy.string({
    produce: () => pipeline.pipeline.pipelineName,
  }),
});

Wednesday, July 2, 2025

VSCode Simple Formatter Setup

Question: What is a simple VSCode formatter setup across projects that require different formatters?

Answer:

VSCode user settings are stored outside the project on local.

VSCode workspace settings are stored in .vscode\settings.json. So in a team environment do set workspace settings and commit to repo. That way the entire team has the same formatter setting.

  • In  File > Preferences > Settings, Enable Format On Save. Simple best/common practice.

  • In  File > Preferences > Settings, Workspace level, set Default Formatter. Different projects are likely to need different formatters. Old projects are probably using old formatters while new projects will want to use new formatters.

Thursday, June 19, 2025

User Guide Mini Crane Scale KLAU Model OCS-L

I purchased this scale and it came with this booklet. However, I couldn't find this guide online so I've copied it here for easy reference.


 







Thursday, November 14, 2024

AWS CDK Get Parameter Store Value

Problem:

There are multiple ways to get a parameter store value. Which one should I use?

Solution:

1. Resolve at deploy time with no extra synth:

Use this pattern when you need the parameter value to resolve at deployment time rather than during `cdk synth`. This avoids CDK context lookups, cached values, and "double synth" behavior when parameters differ per environment.

const value = ssm.StringParameter.fromStringParameterAttributes(this, 'Param', {
  parameterName: '/my/plain/parameter',
}).stringValue;

// For secure parameters
const secret = cdk.SecretValue.secretsManager('/my/secure/parameter');

2. Resolve at synth time:

Use this syntax when you need a fixed, environment-specific value at synthesis time instead of at deployment. This retrieves the actual SSM parameter value during cdk synth and stores it in the cdk.context.json file. Use this approach when conditional logic in your CDK code requires the literal value (e.g., if/else branching to decide which stacks or resources to include).

const value = ssm.StringParameter.valueForStringParameter(this, '/my/plain/parameter');

// For secure parameters
const secret = cdk.SecretValue.ssmParameter('/my/secure/parameter');


3. Synthesis-time value (lookup)

Use this when you need the actual parameter value at synthesis time (not deployment). CDK will resolve it during `cdk synth`, cache it in `cdk.context.json`, and reuse it until refreshed. Ideal for feature flags or conditional logic that must run before deployment. Avoid for frequently changing values—requires re-synth to update.

const value = ssm.StringParameter.valueFromLookup(this, 'my-parameter-name');

https://docs.aws.amazon.com/cdk/v2/guide/get_ssm_value.html

Monday, October 7, 2024

AWS CDK Set CloudFormation Property Escape Hatch

 Problem:

The CDK does not always support all CloudFormation properties. A super simple escape hatch is to use  a addOverride one-liner. There are more robust escape hatches but this is super simple especially for deeply nested properties. Ideally, these are temporary until the CDK exposes properties directly.

Solution:

// The CDK does not currently support dynamic wildcard branch names (and other GitHub version 2 properties) but CloudFormation does.
const cfnPipeline = pipeline.node.defaultChild as codepipeline.CfnPipeline;
cfnPipeline.addOverride('Properties.Stages.0.Actions.0.Configuration.BranchName', `*-${env}-*`);

Wednesday, June 26, 2024

AWS CDK Chart.js Canvas Layer for AWS Lambda

 Problem:

Using the AWS CDK v2, how to deploy the "Canvas Layer for AWS Lambda" serverless application and attach the layer to a Lambda function.

lambda-layer-canvas-nodejs

https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:990551184979:applications~lambda-layer-canvas-nodejs

https://charoitel.github.io/lambda-layer-canvas-nodejs/

To get the latest semanticVersion:

  1. Open the AWS Management Console.
  2. Navigate to the Serverless Application Repository.
  3. Search for lambda-layer-canvas-nodejs.
  4. View the application details to find the latest version.

Solution:

import { Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { CfnApplication } from 'aws-cdk-lib/aws-sam';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lambdaNJS from 'aws-cdk-lib/aws-lambda-nodejs';

export default class ChartStack extends Stack {
    constructor(scope: Construct, id: string, props: cdk.StackProps) {
        super(scope, id, props);

        const chartJsApp = new CfnApplication(this, 'ChartJsApp', {
            location: {
                applicationId: 'arn:aws:serverlessrepo:us-east-1:990551184979:applications/lambda-layer-canvas-nodejs',
                semanticVersion: '2.11.3'
            }
        });

        const layerArn = chartJsApp.getAtt('Outputs.LayerVersion').toString();

        const njs = new lambdaNJS.NodejsFunction(this, 'ChartLambda', {
            entry: 'main.ts',
            handler: 'handler',
            runtime: lambda.Runtime.NODEJS_18_X,
            layers: [lambda.LayerVersion.fromLayerVersionArn(this, 'ChartJsLayer', layerArn)]
        });

        // Add dependency to ensure the layer is deployed before the function
        njs.node.addDependency(chartJsApp);
    }
}

Tuesday, May 28, 2024

AWS CDK V2 Synth Error when Bundling a NodejsFunction

 Problem:
AWS CDK version 2 synth error when bundling a NodejsFunction with somewhat complicated Typescript source code.

Error:
RangeError: Maximum call stack size exceeded

Solution:
Upgrade to a more recent version of npm package "esbuild". In this case, upgrading to version 0.19.12 resolve the issue even though this isn't the most recent version available. Other third party npm package constraints did not allow the latest version to be installed. npm i -D esbuild@0.19.12


Friday, May 3, 2024

AWS Lambda Typescript Ends Unexpectedly

 Problem:

An AWS Lambda in TypeScript ends unexpectedly with a CloudWatch success message (i.e. no errors logged).

Solution:

a. Increase Lambda memory size if low.

b. Check for missing await. Various console.log statements might log to CloudWatch but Lambda does not run to completion.

Wednesday, March 20, 2024

Developer Setup on Windows

Windows

  1. Display settings.

Install 

  1. Google Chrome
    • Make default browser
    • Plugins:
      • AWS Extend Switch Roles
      • Bitwarden
      • Session Buddy
  2. Firefox + Edge + Brave
  3. NVidia GeForce Experience (use to download latest drivers)
  4. Git for Windows
  5. TortoiseGit
    • git config --global --add safe.directory 'c:/myfolder'
    • github will prompt to login via browser
  6. Visual Studio Code
  7. Node.js includes npm
  8. AWS CLI
  9. MySQL Workbench
  10. Notepad++
  11. Draw.io
  12. SnagIt
  13. Camtasia
  14. MS office + teams + skype
    •  Configure Outlook to open links in default browser.
  15. Open OneDrive and login to accounts to view files on local
  16. Adobe Acrobat Reader
NPM
  • npm install -g @ionic/cli
  • npm install -g @angular/cli
Visual Studio Code
  • Command Palette > Open User Settings JSON
    {
        "typescript.implementationsCodeLens.enabled": true,
        "[typescript]": {
            "editor.detectIndentation": false,
            "editor.tabSize": 4,
        },
        "[html]": {
            "editor.detectIndentation": false,
            "editor.tabSize": 4
        }
    }

Troubleshooting
  • speedtest.net (internet connection speed test)
  • 3DMark demo (for basic GPU/CPU benchmark)

Friday, March 8, 2024

SuperMicro Desktop Workstation Build 2024

Supermicro Full-Tower SuperWorkstation (SYS-551A-T)

CPU
1 x Intel® Xeon® W5-3435X Processor 16-Core 3.10 GHz 45MB Cache (270W) 

Memory
2 x 32GB DDR5 4800MHz ECC RDIMM Server Memory 

Storage
1 x 1.9TB 2.5" 7450 PRO NVMe (7mm) PCIe 4.0 Solid State Drive (1 x DWPD) 

Networking
1 x 1 x 10Gb E
 
GPU
1 x NVIDIA Quadro RTX A4000 16GB GDDR6 PCIe 4.0 x16 - 4 DisplayPort (140W) 

Accessory
1 x MCP-220-73102-0N - 3.5" to 2.5" Converter Drive Tray (Required Accessory)
1 x MiniSAS HD to U.3 with Power Cable (Required Accessory) 
1 x CBL-0082L - Y Split SATA Power Adapter (Required Accessory)
1 x CBL-SAST-0624 - SATA 70cm Cable (Required Accessory)
1 x DVM-TEAC-DVDRW24-HBT - Slim DVD-RW SATA Drive (Required Accessory)
1 x SKT-1333L-0000-FXC - E1A Carrier (Required Accessory)
1 x SNK-P0091AP4 - 4U Active CPU Heat Sink (Required Accessory)
1 x FAN-0222L4 - 120MM Fan (Required Accessory)

Operating System
1 x Windows 11 Professional 64-Bit

Display
2 x Acer Predator XB273K Pbmiphzx 27" UHD (3840 x 2160) IPS Monitor with NVIDIA G-SYNC

I/O Ports

Front:

    • two USB2.0 ports
    • two USB3.2 Gen1 (5 G) Type A ports
    • one USB3.2 Gen2 (10 G) Type C port
    • one Power Button
    • one Audio In, one Mic In

Button Rear:

    • one 10 Gb LAN port
    • one 1Gb LAN port
    • one USB3.2 Gen2 x2 (20 Gbps) Type C port
    • four USB3.2 Gen2 x1 ports
    • two USB2.0 ports
    • one VGA port (for BMC interface)
    • HD Audio 7.1 Channel connectors
    • one COM port

Onboard:

    • one USB3.2 Gen 2 Type C header
    • two USB3.2 Gen1 (5 G) headers
    • two USB2.0 headers
    • ten 4-pin fan headers
    • one 1 2V power header for water cooling pump
    • one DOM PW connector
    • one TPM 2.0 header

SuperWorkstation SYS-551A-T
SYS-551A-T Manual

Problem 1:
Displays message "checking media presence" and displays the BIOS page.
Support Wrote:
press F11 to the boot menu. It should have the "UEFI: Windows OS" option. Check the U.2 drive cable inside the chassis.  Make sure that the cable was connected properly on both U.2 connector and U.2 drive. 
Solution 1:
The cable was not plugged into the back of the system drive located in one of the drive bays. Simply plugging the cable in resolved this issue. The cabling bundle tie is too tight. It needs to be cut to give the cables more slack.

Problem 2:
Windows 11 is not activated.
Solution 2:
Bottom of chassis contains a Windows sticker. Lightly scratch the silver part to reveal the rest of the 25 character Windows activation code. Settings > Activation settings > Change product key (enter key from sticker).

Problem 3:
Windows 11 is so slow it's basically unusable. e.g. File explorer takes 10 secs to display completely.
Solution 3:
Set: Control Panel > Power Options > High Performance

Problem 4:
Windows 11, "system > display" shows 3 monitors. One of them is labelled "1" and is a phantom (i.e. this physical monitor doesn't exist). Clicking "disconnect this display" does not fix the problem.
Solution 4:
?

Tuesday, October 23, 2018

Ionic 4 + Capacitor + Firebase Messaging + iOS Proof of Concept

Problem:

How to get Firebase FCM device token from iOS device in an Ionic 4.beta and Capacitor 1.0.0-beta.8 project.

Solution:

Capacitor push notifications on an Android device returns an FCM device token. However, iOS devices return an APNS device token. Firebase is unable to send a message with an APNS token. However, the APNS token could be used to send a message via Apple's Push Notification Service.

To get an FCM on an iOS device, follow the instructions here for setting up a Firebase Cloud Message Client App on iOS: https://firebase.google.com/docs/cloud-messaging/ios/client

Proof of Concept (in short):

a. Add Firebase pods to /ios/App/Podfile


target 'App' do
  # Add your Pods here
  pod 'Firebase/Core'
  pod 'Firebase/Messaging'

b. Run in the console in /ios/App: pod install

c. In /ios/App/App/AppDelegate.swift insert the following:

// part 1 of 3

import UserNotifications
import Firebase

// part 2 of 3

// Override point for customization after application launch.
    
    // Use Firebase library to configure APIs
    FirebaseApp.configure()
    
    Messaging.messaging().delegate = self
    
    if #available(iOS 10.0, *) {
        // For iOS 10 display notification (sent via APNS)
        UNUserNotificationCenter.current().delegate = self
        
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: {_, _ in })
    } else {
        let settings: UIUserNotificationSettings =
            UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(settings)
    }
    
    application.registerForRemoteNotifications()

// part 3 of 3
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
        print("Firebase registration token: \(fcmToken)")
        
        let dataDict:[String: String] = ["token": fcmToken]
        NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
        // TODO: If necessary send token to application server.
        // Note: This callback is fired at each app startup and whenever a new token is generated.
    }

Friday, October 12, 2018

Angular 6 Component Require JSON ExpressionChangedAfterItHasBeenCheckedError

Problem:

In an Angular 6 project, a simple component that gets json data from a local file generates error: ExpressionChangedAfterItHasBeenCheckedError

Solution:

Do not use the following method to import local json data into the component:
const data = require('./data.json');

Use other standard approaches e.g.

this.http.get(this.dataUrl).subscribe((data: any) => {
    // Do something with json data!
});

Saturday, August 11, 2018

Ionic 4 Debug With Chrome Sources

Problem
In Ionic 3, it was easy to find source .ts code in Chrome's developer tools "Sources" tab for debugging. In Ionic4, it's difficult to find.

Solution:
In Chrome developer tools "Sources" tab drill into:
webpack:// > . > src > app



Ionic 4 + Capacitor Calling Local API Blocked Mixed Content Error

Problem:
Ionic 4 + Capacitor app running locally on device. NodeJS + Express + MongoDB API running local on http (not https).

Can hit local API successfully when running Ionic in browser on API url localhost or IPv4 address (e.g. 192.168.15.8).

When running on device (connected via USB) get the following error on all API calls (in Chrome developer tools network tab): (blocked-mixed-content)

Solution:
Add: "allowMixedContent": true
To: \capacitor.config.json
https://github.com/ionic-team/capacitor/issues/630

Tuesday, April 24, 2018

Windows 10 Boot Failure Error Code 0xc000000e

Problem:
Windows tries to load but fails with blue screen.

Recovery
Your PC/Device needs to be repaired
The application or operating system couldn’t be loaded because a required file is missing or contains errors.
File: \Windows\system32\winload.exe
Error Code:0xc000000e



Solution:

I was unable to recover from this error! But Peter was able to -- highly recommended -- he knows his stuff: http://www.peterspcrepair.com/

Notes based on my limited understanding of the problem:

1.
This was one of the clearest articles I could find.
https://www.lifewire.com/how-to-rebuild-the-bcd-in-windows-2624508
However, my understanding is it's not a suitable fix for a UEFI SSD system drive.

2.
This was one of the clearest articles I could find suitable for UEFI.
https://www.easeus.com/partition-manager-software/fix-uefi-boot-in-windows-10-8-7.html#part5

My results from command prompt: list vol



What tripped me up is I kept thinking the UEFI volume was the same as the system drive. I could assign a letter and see the files on my system drive (i.e. my C:\ drive with windows). But this is the wrong drive to use for bcdboot. The UEFI is apparently always FAT32. I "think" I should have been using volume 5. Volume 7 seems to be from my Windows 10 recovery disk.

So I should have been running (from command prompt) this:
diskpart
sel disk 0
list vol
sel vol 5
assign letter=G: Note: G is a unique drive letter not already in use.

3.
Restoring from a recent restore point did NOT resolve the issue. But was done before the boot repair above.

4.
BIOS boot mode changed from "Dual" to "UEFI". Unclear if this was a necessary fix. My understanding is this was NOT necessary. PC had been working with zero issues for the past 3 months.

Friday, January 19, 2018

SuperMicro Desktop Workstation Build 2018

Personal SuperMicro Desktop Workstation Build 2018


Notes

  • Happy with price/value/performance.
  • A key requirement was a motherboard with at least one Thunderbolt 3 port.
  • SuperMicro chasis made building the PC very simple and worth every cent. Not visually appealing but not ugly. Fairly quiet.
  • CPU is hitting 100% for minutes with WAMP / Magento 2. In hindsight, would choose a motherboard that supports Xeon E5 which would have allowed for a CPU with more than 4 cores.
  • Broke the first motherboard unplugging the monster GPU. Additional cost to junk/replace.
  • BIOS bootup time seems long. ~15 secs.
  • Chasis front panel plug to motherboard not keyed. Easy to plug in the wrong way. Cable is short, so harder to plugin correct way.
  • More USB ports on the back needed.


SuperMicro Support Q&A


Question: How do I install Windows 10 to the blank system SSD from USB.

Answer: OS must be installed with UEFI mode for M.2 SSD. See youtube link as a reference. 
https://www.youtube.com/watch?v=vmFhB1-X-PQ

Question: What is the correct boot order to boot of the SSD system drive.

Answer: Change “UEFI Hard Disk: Windows Boot manager” to boot order #1.

Question: BIOS boot time is slow ~15 secs. How can I improve the speed.

Answer: BIOS needs to detect all the devices inside the system before booting to OS. You can try to disable all the PCIe slots option rom inside the BIOS and disable all the unnecessary features inside the BIOS like serial port.

Question: GPU covers the SSD M.2 port and is awkward to get it in and out. Can I use another port as it would make it easier to install and I’d have direct access to the SSD (if needed).

Answer: you can use slot #2 for your GPU if you don’t have any PCIe card on slot #4. If you have PCIe cards on both slot #2 & #4, then both slots will run as x8.

Components Checklist

  • Motherboard
  • CPU
  • CPU Heatsink
  • CPU Thermal Paste (just in case)
  • RAM
  • GPU
  • Chasis
  • SSD (system)
  • HDD (data)
  • SSD (portable/external)

Components


Motherboard
Supermicro Motherboard ATX for up to Xeon E3-1200v5
SuperMicro X11SAT (-F IPMI support was out of stock)

CPU
Intel Xeon E3-1275 v6 Kaby Lake 3.8 GHz 4 x 256KB L2 Cache 8MB L3 Cache LGA 1151 73W BX80677E31275V6 Server Processor

Interesting article on why to choose Xeon:

CPU Heatsink
Supermicro 2U Active CPU Heat Sink Socket LGA1150/1155 (SNK-P0046A4)

CPU Thermal Paste
Arctic Silver 5 High-Density Polysynthetic Silver Thermal Compound AS5-3.5G
*Didn't need because heatsink came with grease. Buy just in case heatsink needs to be removed.

RAM/Memory
Supermicro 16GB 288-Pin DDR4 2400 (PC4 19200) Server Memory (MEM-DR416L-SL01-EU24)
4 x $206 = $824

GPU
Nvidia GTX 1070 Ti
*Nvidia GTX 1080 Ti (preferred but out of stock globally).

Chassis/Case
SC743TQ-1200B-SQ 
865 Watts
SUPERMICRO CSE-743TQ-865B-SQ Black Pedestal Server Case 865W 2 External 5.25" Drive Bays

Power watts/calculator:

SSD System 1TB
SAMSUNG 960 PRO M.2 1TB NVMe PCI-Express 3.0 x4 Internal Solid State Drive (SSD) MZ-V6P1T0BW
  
HDD Data
WD Black 2TB Performance Desktop Hard Disk Drive - 7200 RPM SATA 2Gb/s 64MB Cache 3.5 Inch - WD2003FZEX

HDD Backup
WD Blue 6TB Desktop Hard Disk Drive - 5400 RPM SATA 6Gb/s 64MB Cache 3.5 Inch - WD60EZRZ

External SSD
Samsung Portable SSD T5 540 MB/s
*Temporary until a good/reliable/portable Thunderbolt 3 external drive available.

Friday, July 21, 2017

Magento 2 Enable Product on Import

Problem:
How to enable (or explicitly disable) a product using Magento 2 out-of-the-box product import.

Solution:
Include column product_online in the import and set values (1=enable, 0=disable) accordingly. Note that we'd expect this column to be called status instead since this is the attribute name. But adding column status instead does not work.

Friday, May 26, 2017

Magento 2.1 SOAP API Basics

Version: Magento 2.1+

The Magento SOAP API is made up of many services. Each service contains API endpoints.

Services that return sensitive data are secure and require a security token to access e.g. salesOrderRepositoryV1GetList. Services that do not return sensitive information do not require a token and are publicly available e.g. directoryCountryInformationAcquirerV1GetCountriesInfo

List of anonymous guest services is here: /soap/default?wsdl_list=1

Magento admin > Configuration > Services > Web API Security > Allow Anonymous Guest Access = Yes will allow additional anonymous guest services to be accessible. These services may return somewhat sensitive data e.g. cmsPageRepositoryV1.

Specify the service in the WSDL url. Specify multiple services in the WSDL url as needed. e.g. /soap/default?wsdl&services=customerCustomerRepositoryV1,salesOrderRepositoryV1

A token can be obtained by creating in Magento admin > System > Integrations > Create New Integration. Use the Access Token in the header of SOAP calls. e.g. $opts = ['http' => ['header' => "Authorization: Bearer " . $token]];

A token can also be obtained by creating a Magento admin user and then requesting a token based on the username/password e.g. $token = $request->integrationAdminTokenServiceV1CreateAdminAccessToken(array("username"=>"myusername", "password"=>"mypassword"));

Calling SOAP APIs from a PHP script may cache WSDL files on the client. For example, it was not possible to call protected APIs with a token. After deleting client wsdl files in /tmp folder the issue was resolved.

Wednesday, May 24, 2017

Magento Custom Multi Select Customer Attribute

Version: Magento 1.x

Problem:
Create a simple custom multi select customer attribute programmatically via upgrade script.

Solution:

$attributeCode = 'my_attribute';
$installer->addAttribute('customer', $attributeCode, array(
    'type' => 'varchar',
    'label' => 'My Attribute',
    'input' => 'multiselect',
    'source' => 'eav/entity_attribute_source_table',
    'backend' => '',
    'visible' => false,
    'required' => false,
    'unique' => false,
    'option' => array (
        'value' => array(
            'Option1' => array('Option1'),
            'Option2' => array('Option2')
        )
    )
));

$attribute = Mage::getSingleton('eav/config')
    ->getAttribute('customer', $attributeCode);
$attribute
    ->setData('used_in_forms', array('customer_account_edit'))
    ->setData('is_used_for_customer_segment', true)
    ->setData('is_system', false)
    ->setData('is_user_defined', true)
    ->setData('is_visible', false)
    ->setData('sort_order', 100);
$attribute->save();

Monday, April 3, 2017

Problem:
Encode js strings in PHP.

Solution:
$encodedStr = addslashes(htmlspecialchars($str));