diff --git a/Orca.xcodeproj/project.pbxproj b/Orca.xcodeproj/project.pbxproj index eff354ae..a039428e 100644 --- a/Orca.xcodeproj/project.pbxproj +++ b/Orca.xcodeproj/project.pbxproj @@ -3462,6 +3462,14 @@ 84FFCAA90636D5B10069432F /* ORCaen792Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 84FFCAA30636D5B10069432F /* ORCaen792Controller.m */; }; 84FFCAAA0636D5B10069432F /* ORCaen792Model.h in Headers */ = {isa = PBXBuildFile; fileRef = 84FFCAA40636D5B10069432F /* ORCaen792Model.h */; }; 84FFCAAB0636D5B10069432F /* ORCaen792Model.m in Sources */ = {isa = PBXBuildFile; fileRef = 84FFCAA50636D5B10069432F /* ORCaen792Model.m */; }; + 863287B12F1F22600004C519 /* ORDefender3000ModelNew.h in Headers */ = {isa = PBXBuildFile; fileRef = 863287AA2F1F22600004C519 /* ORDefender3000ModelNew.h */; }; + 863287B22F1F22600004C519 /* ORDefender3000ControllerNew.h in Headers */ = {isa = PBXBuildFile; fileRef = 863287AC2F1F22600004C519 /* ORDefender3000ControllerNew.h */; }; + 863287B32F1F22600004C519 /* ORDefender3000DecodersNew.h in Headers */ = {isa = PBXBuildFile; fileRef = 863287AE2F1F22600004C519 /* ORDefender3000DecodersNew.h */; }; + 863287B42F1F22600004C519 /* Defender3000New.tif in Resources */ = {isa = PBXBuildFile; fileRef = 863287A92F1F22600004C519 /* Defender3000New.tif */; }; + 863287B52F1F22600004C519 /* Defender3000New.nib in Resources */ = {isa = PBXBuildFile; fileRef = 863287A82F1F22600004C519 /* Defender3000New.nib */; }; + 863287B62F1F22600004C519 /* ORDefender3000ControllerNew.m in Sources */ = {isa = PBXBuildFile; fileRef = 863287AD2F1F22600004C519 /* ORDefender3000ControllerNew.m */; }; + 863287B72F1F22600004C519 /* ORDefender3000DecodersNew.m in Sources */ = {isa = PBXBuildFile; fileRef = 863287AF2F1F22600004C519 /* ORDefender3000DecodersNew.m */; }; + 863287B82F1F22600004C519 /* ORDefender3000ModelNew.m in Sources */ = {isa = PBXBuildFile; fileRef = 863287AB2F1F22600004C519 /* ORDefender3000ModelNew.m */; }; 9C086CE90D10AB6200524F47 /* mainFocalPlaneDetector.tif in Resources */ = {isa = PBXBuildFile; fileRef = 9C086CE80D10AB6200524F47 /* mainFocalPlaneDetector.tif */; }; 9C1363C70D0A7921006C550D /* Caen265.nib in Resources */ = {isa = PBXBuildFile; fileRef = 9C1363BF0D0A7921006C550D /* Caen265.nib */; }; 9C1363C80D0A7921006C550D /* Caen265Card.tif in Resources */ = {isa = PBXBuildFile; fileRef = 9C1363C00D0A7921006C550D /* Caen265Card.tif */; }; @@ -7439,6 +7447,14 @@ 84FFCAA30636D5B10069432F /* ORCaen792Controller.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ORCaen792Controller.m; sourceTree = ""; }; 84FFCAA40636D5B10069432F /* ORCaen792Model.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ORCaen792Model.h; sourceTree = ""; }; 84FFCAA50636D5B10069432F /* ORCaen792Model.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = ORCaen792Model.m; sourceTree = ""; }; + 863287A82F1F22600004C519 /* Defender3000New.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = Defender3000New.nib; sourceTree = ""; }; + 863287A92F1F22600004C519 /* Defender3000New.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Defender3000New.tif; sourceTree = ""; }; + 863287AA2F1F22600004C519 /* ORDefender3000ModelNew.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORDefender3000ModelNew.h; sourceTree = ""; }; + 863287AB2F1F22600004C519 /* ORDefender3000ModelNew.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORDefender3000ModelNew.m; sourceTree = ""; }; + 863287AC2F1F22600004C519 /* ORDefender3000ControllerNew.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORDefender3000ControllerNew.h; sourceTree = ""; }; + 863287AD2F1F22600004C519 /* ORDefender3000ControllerNew.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORDefender3000ControllerNew.m; sourceTree = ""; }; + 863287AE2F1F22600004C519 /* ORDefender3000DecodersNew.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ORDefender3000DecodersNew.h; sourceTree = ""; }; + 863287AF2F1F22600004C519 /* ORDefender3000DecodersNew.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ORDefender3000DecodersNew.m; sourceTree = ""; }; 9C086CE80D10AB6200524F47 /* mainFocalPlaneDetector.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = mainFocalPlaneDetector.tif; path = "Source/Objects/Hardware/I2C/Custom Hardware/KATRIN Hardware/eGun/mainFocalPlaneDetector.tif"; sourceTree = SOURCE_ROOT; }; 9C1363BF0D0A7921006C550D /* Caen265.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = Caen265.nib; path = Source/Objects/Hardware/Vme/CAEN/CV265/Caen265.nib; sourceTree = SOURCE_ROOT; }; 9C1363C00D0A7921006C550D /* Caen265Card.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = Caen265Card.tif; path = Source/Objects/Hardware/Vme/CAEN/CV265/Caen265Card.tif; sourceTree = SOURCE_ROOT; }; @@ -10530,6 +10546,7 @@ 84B28CD50F4C597900E2B056 /* BocTIC3 */, 84499CBD0F13E457004B855B /* CTITemp */, 8407F05F2BF3A90D00668A6C /* Defender3000 */, + 863287B02F1F22600004C519 /* Defender3000New */, 84499B6E0F13BB6E004B855B /* MksPdr2000 */, 84098F4D0F964F0100036BE8 /* PDcu */, 840D56D70F39E9BF00F9A274 /* Pac */, @@ -15201,6 +15218,21 @@ path = Source/Objects/Hardware/Vme/CAEN/CV792; sourceTree = SOURCE_ROOT; }; + 863287B02F1F22600004C519 /* Defender3000New */ = { + isa = PBXGroup; + children = ( + 863287A82F1F22600004C519 /* Defender3000New.nib */, + 863287A92F1F22600004C519 /* Defender3000New.tif */, + 863287AA2F1F22600004C519 /* ORDefender3000ModelNew.h */, + 863287AB2F1F22600004C519 /* ORDefender3000ModelNew.m */, + 863287AC2F1F22600004C519 /* ORDefender3000ControllerNew.h */, + 863287AD2F1F22600004C519 /* ORDefender3000ControllerNew.m */, + 863287AE2F1F22600004C519 /* ORDefender3000DecodersNew.h */, + 863287AF2F1F22600004C519 /* ORDefender3000DecodersNew.m */, + ); + path = Defender3000New; + sourceTree = ""; + }; 9C1363BE0D0A7921006C550D /* CV265 */ = { isa = PBXGroup; children = ( @@ -16325,6 +16357,7 @@ 8434A200055B3287002D3102 /* ORWaveformController.h in Headers */, 8489177A1D6B73D300CF5AAF /* ORCytecVM8Controller.h in Headers */, 8434A201055B3287002D3102 /* ORGenericData.h in Headers */, + 863287B32F1F22600004C519 /* ORDefender3000DecodersNew.h in Headers */, 8434A202055B3287002D3102 /* ORGpibDeviceModel.h in Headers */, 8434A203055B3287002D3102 /* ORHPPulserModel.h in Headers */, 8434A204055B3287002D3102 /* Utilities.h in Headers */, @@ -16429,6 +16462,7 @@ 8468E6FA06932C3F00B57CE8 /* NcdLogAmpTask.h in Headers */, 846798C5069475DA00DF8B2A /* StatusLog.h in Headers */, 846798E9069488AE00DF8B2A /* NcdLinearityTask.h in Headers */, + 863287B22F1F22600004C519 /* ORDefender3000ControllerNew.h in Headers */, 4AB9E5331DE5D820007C75E0 /* postgres_ext.h in Headers */, 846799570694B82200DF8B2A /* NcdThresholdTask.h in Headers */, 84F9836D06A441CF0087FA3E /* ORGTIDGenerator.h in Headers */, @@ -16516,6 +16550,7 @@ 84749D1F07D6526F001553EC /* ORM321Model.h in Headers */, A87BA18E2C6817C400E14CCE /* timestamps.h in Headers */, 84749D2407D6526F001553EC /* ORMCarrierController.h in Headers */, + 863287B12F1F22600004C519 /* ORDefender3000ModelNew.h in Headers */, 84749D2607D6526F001553EC /* ORMCarrierModel.h in Headers */, 84749D7107D663A2001553EC /* ORVmeMCard.h in Headers */, 84749DC607D66BDF001553EC /* ORVmeDaughterCard.h in Headers */, @@ -18155,6 +18190,7 @@ 84AB8BD00D2314DD00EC39F2 /* JAMF.gif in Resources */, 84AB8BD10D2314DD00EC39F2 /* JAMF.nib in Resources */, 84A8B14A0D35702300263D31 /* SBC_LAM.gif in Resources */, + 863287B52F1F22600004C519 /* Defender3000New.nib in Resources */, 84A8B14B0D35702300263D31 /* SBC_LAM.nib in Resources */, 84A5CD590D464F4600D9833C /* Filter.nib in Resources */, 84A5CD5A0D464F4600D9833C /* Filter.tif in Resources */, @@ -18487,6 +18523,7 @@ 8472AA7B12DB44B400DEEB02 /* MPodC.tif in Resources */, 8472AA8012DB44B400DEEB02 /* MPodMiniCrate.nib in Resources */, 8472AA8112DB44B400DEEB02 /* MPodMiniCrate.tif in Resources */, + 863287B42F1F22600004C519 /* Defender3000New.tif in Resources */, 8472AA8212DB44B400DEEB02 /* MPodMiniCrateSmall.tif in Resources */, 842544EA12F1FF9F00472314 /* BamDetector.nib in Resources */, 842544EB12F1FF9F00472314 /* BamDetector.tif in Resources */, @@ -19065,6 +19102,7 @@ 2A41A2B6089AB2A0003D77DD /* ORScalerSum.m in Sources */, 2A943A6508A8194B00D04541 /* ORSerialPort.m in Sources */, 2A943A6708A8194B00D04541 /* ORSerialPortAdditions.m in Sources */, + 863287B82F1F22600004C519 /* ORDefender3000ModelNew.m in Sources */, 8494F8D31C440E2C00A35F8B /* ORMJDDewarScaleController.m in Sources */, 2A943A6908A8194B00D04541 /* ORSerialPortList.m in Sources */, 2A943A6B08A8194B00D04541 /* ORStandardEnumerator.m in Sources */, @@ -19521,6 +19559,7 @@ 84D359CD0FB487AA005F429B /* ORMCA927Decoders.m in Sources */, 8408322C0FC3307F002B2394 /* ORLongTermView.m in Sources */, 84B194BC0FC44E1800775CF1 /* ORMotionNodeDecoders.m in Sources */, + 863287B72F1F22600004C519 /* ORDefender3000DecodersNew.m in Sources */, 146822440FC4799C0082BD70 /* ORCircularBufferUV.m in Sources */, 8408A22B0FD85B3A00B0206D /* ORTemplates.m in Sources */, 84B74CEA0FEBE9B90033E658 /* ORCaen965Controller.m in Sources */, @@ -19689,6 +19728,7 @@ 8449CC88123E85DA009C8AA2 /* ORVHSC040nModel.m in Sources */, 0FB2022F1CDFCF4E0083F552 /* TUBiiController.m in Sources */, 84E9F6A1123FE4D600116607 /* ORNHQ226LController.m in Sources */, + 863287B62F1F22600004C519 /* ORDefender3000ControllerNew.m in Sources */, 84E9F6A3123FE4D600116607 /* ORNHQ226LDecoders.m in Sources */, 84E9F6A5123FE4D600116607 /* ORNHQ226LModel.m in Sources */, 8475D8181A3665BC00EE4DE4 /* ORMJDInterlocks.m in Sources */, diff --git a/Source/Experiments/LEGEND/L200/ORL200DetectorView.m b/Source/Experiments/LEGEND/L200/ORL200DetectorView.m index dcbb642d..d41ba7e8 100644 --- a/Source/Experiments/LEGEND/L200/ORL200DetectorView.m +++ b/Source/Experiments/LEGEND/L200/ORL200DetectorView.m @@ -47,7 +47,7 @@ #define kL200CC4InnerR (kL200CC4Offset*2-5) #define kL200CC4OuterR (kL200CC4Offset*2 + 2*kL200CC4Size*7+10) #define kL200CC4DeltaAngle (360/kNumCC4Positions) -static NSInteger NumberofTimesCall = 0; +//static NSInteger NumberofTimesCall = 0; @interface ORL200DetectorView (private) - (void) makeAllSegments; @@ -212,11 +212,11 @@ - (void) drawRect:(NSRect)rect - (NSColor*) getColorForSet:(int)setIndex value:(float)aValue { - if (NumberofTimesCall==1000){ //only calling to make source once in 1000 times - [self makeSource]; - NumberofTimesCall=0; - } - NumberofTimesCall++; + //if (NumberofTimesCall==10000){ //only calling to make source once in 1000 times + // [self makeSource]; + // NumberofTimesCall=0; + //} + //NumberofTimesCall++; if(setIndex == kL200DetType) return [detColorScale getColorForValue:aValue]; else if(setIndex == kL200SiPMType) return [sipmColorScale getColorForValue:aValue]; else if(setIndex == kL200PMTType) return [pmtColorScale getColorForValue:aValue]; @@ -1024,6 +1024,7 @@ -(void) makeSource } -(void)drawSourceLabel{ NSFont* font = [NSFont fontWithName:@"Geneva" size:7]; + [sourceLabelAttr release]; sourceLabelAttr = [[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, [NSColor systemRedColor], NSForegroundColorAttributeName, nil] retain]; for(int i=0; i<4; i++){ diff --git a/Source/Main Dialogs/Catalog/Catalog.nib/designable.nib b/Source/Main Dialogs/Catalog/Catalog.nib/designable.nib index e4dbf4bf..14970c02 100644 --- a/Source/Main Dialogs/Catalog/Catalog.nib/designable.nib +++ b/Source/Main Dialogs/Catalog/Catalog.nib/designable.nib @@ -1,8 +1,8 @@ - + - + @@ -16,20 +16,20 @@ - - + + - + - + - + @@ -173,14 +173,14 @@ - + - + @@ -202,7 +202,7 @@ + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.nib/keyedobjects-101300.nib b/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.nib/keyedobjects-101300.nib new file mode 100644 index 00000000..d83fd5cd Binary files /dev/null and b/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.nib/keyedobjects-101300.nib differ diff --git a/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.nib/keyedobjects.nib b/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.nib/keyedobjects.nib new file mode 100644 index 00000000..5b2b0a54 Binary files /dev/null and b/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.nib/keyedobjects.nib differ diff --git a/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.tif b/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.tif new file mode 100644 index 00000000..47628943 Binary files /dev/null and b/Source/Objects/Hardware/Serial/Defender3000New/Defender3000New.tif differ diff --git a/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ControllerNew.h b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ControllerNew.h new file mode 100644 index 00000000..31c32ef4 --- /dev/null +++ b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ControllerNew.h @@ -0,0 +1,83 @@ +//-------------------------------------------------------- +// ORDefender3000Controller +// Orca +// +// Created by Mark Howe on 05/14/2024. +// Copyright 2024 CENPA, University of North Carolina. All rights reserved. +//----------------------------------------------------------- +//This program was prepared for the Regents of the University of +//North Carolina sponsored in part by the United States +//Department of Energy (DOE) under Grant #DE-FG02-97ER41020. +//The University has certain rights in the program pursuant to +//the contract and the program should not be copied or distributed +//outside your organization. The DOE and the University of +//North Carolina reserve all rights in the program. Neither the authors, +//University of North Carolina, or U.S. Government make any warranty, +//express or implied, or assume any liability or responsibility +//for the use of this software. +//------------------------------------------------------------- +#pragma mark ***Imported Files + +@class ORCompositeTimeLineView; + +@interface ORDefender3000ControllerNew : OrcaObjectController +{ + IBOutlet NSTextField* lockDocField; + IBOutlet NSButton* shipWeightButton; + IBOutlet NSButton* lockButton; + IBOutlet NSButton* sendCmdButton; + IBOutlet NSTextField* portStateField; + IBOutlet NSPopUpButton* portListPopup; + IBOutlet NSPopUpButton* pollTimePopup; + IBOutlet NSPopUpButton* commandPopup; + IBOutlet NSPopUpButton* unitsPopup; + IBOutlet NSButton* openPortButton; + IBOutlet NSButton* sendAllButton; + IBOutlet NSTextField* weightField; + IBOutlet NSTextField* timeField; + IBOutlet NSTextField* unitsField; + IBOutlet NSTextField* printIntervalField; + IBOutlet NSTextField* tareField; + IBOutlet ORCompositeTimeLineView* plotter0; +} + +#pragma mark ***Initialization +- (id) init; +- (void) dealloc; +- (void) awakeFromNib; + +#pragma mark ***Notifications +- (void) registerNotificationObservers; +- (void) updateWindow; + +#pragma mark ***Interface Management +- (void) updateTimePlot:(NSNotification*)aNote; +- (void) scaleAction:(NSNotification*)aNote; +- (void) shipWeightChanged:(NSNotification*)aNote; +- (void) lockChanged:(NSNotification*)aNote; +- (void) portNameChanged:(NSNotification*)aNote; +- (void) portStateChanged:(NSNotification*)aNote; +- (void) weightChanged:(NSNotification*)aNote; +- (void) pollTimeChanged:(NSNotification*)aNote; +- (void) miscAttributesChanged:(NSNotification*)aNote; +- (void) unitsChanged:(NSNotification*)aNote; +- (void) commandChanged:(NSNotification*)aNote; +- (void) updateButtonStates; + +#pragma mark ***Actions +- (IBAction) shipWeightAction:(id)sender; +- (IBAction) lockAction:(id) sender; +- (IBAction) portListAction:(id) sender; +- (IBAction) openPortAction:(id)sender; +- (IBAction) sendCommandAction:(id)sender; +- (IBAction) pollTimeAction:(id)sender; +- (IBAction) printIntervalAction:(id)sender; +- (IBAction) tareAction:(id)sender; +- (IBAction) unitsAction:(id)sender; + +- (int) numberPointsInPlot:(id)aPlotter; +- (void) plotter:(id)aPlotter index:(int)i x:(double*)xValue y:(double*)yValue; + +@end + + diff --git a/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ControllerNew.m b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ControllerNew.m new file mode 100644 index 00000000..8db2efb9 --- /dev/null +++ b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ControllerNew.m @@ -0,0 +1,427 @@ +//-------------------------------------------------------- +// ORDefender3000Controller +// Orca +// +// Created by Mark Howe on 05/14/2024. +// Copyright 2024 CENPA, University of North Carolina. All rights reserved. +//----------------------------------------------------------- +//This program was prepared for the Regents of the University of +//North Carolina sponsored in part by the United States +//Department of Energy (DOE) under Grant #DE-FG02-97ER41020. +//The University has certain rights in the program pursuant to +//the contract and the program should not be copied or distributed +//outside your organization. The DOE and the University of +//North Carolina reserve all rights in the program. Neither the authors, +//University of North Carolina, or U.S. Government make any warranty, +//express or implied, or assume any liability or responsibility +//for the use of this software. +//------------------------------------------------------------- +#pragma mark ***Imported Files + +#import "ORDefender3000ControllerNew.h" +#import "ORDefender3000ModelNew.h" +#import "ORTimeLinePlot.h" +#import "ORCompositePlotView.h" +#import "ORTimeAxis.h" +#import "ORSerialPortList.h" +#import "ORSerialPort.h" +#import "ORTimeRate.h" + +@interface ORDefender3000ControllerNew (private) +- (void) populatePortListPopup; +@end + +@implementation ORDefender3000ControllerNew + +#pragma mark ***Initialization + +- (id) init +{ + self = [super initWithWindowNibName:@"Defender3000New"]; + return self; +} + +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void) awakeFromNib +{ + [self populatePortListPopup]; + [[plotter0 yAxis] setRngLow:0.0 withHigh:300.]; + [[plotter0 yAxis] setRngLimitsLow:-300.0 withHigh:500 withMinRng:4]; + + [[plotter0 xAxis] setRngLow:0.0 withHigh:10000]; + [[plotter0 xAxis] setRngLimitsLow:0.0 withHigh:200000. withMinRng:200]; + + ORTimeLinePlot* aPlot; + aPlot= [[ORTimeLinePlot alloc] initWithTag:0 andDataSource:self]; + [plotter0 addPlot: aPlot]; + [(ORTimeAxis*)[plotter0 xAxis] setStartTime: [[NSDate date] timeIntervalSince1970]]; + [aPlot release]; + + [super awakeFromNib]; +} + +- (void) setModel:(id)aModel +{ + [super setModel:aModel]; + [[self window] setTitle:[NSString stringWithFormat:@"Defender 3000 New (Unit %u)",[model uniqueIdNumber]]]; +} + +#pragma mark ***Notifications + +- (void) registerNotificationObservers +{ + NSNotificationCenter* notifyCenter = [NSNotificationCenter defaultCenter]; + [super registerNotificationObservers]; + [notifyCenter addObserver : self + selector : @selector(lockChanged:) + name : ORRunStatusChangedNotification + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(lockChanged:) + name : ORDefender3000NewLock + object: nil]; + + [notifyCenter addObserver : self + selector : @selector(portNameChanged:) + name : ORDefender3000ModelNewPortNameChanged + object: nil]; + + [notifyCenter addObserver : self + selector : @selector(portStateChanged:) + name : ORSerialPortStateChanged + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(weightChanged:) + name : ORDefender3000NewWeightChanged + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(pollTimeChanged:) + name : ORDefender3000ModelNewPollTimeChanged + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(shipWeightChanged:) + name : ORDefender3000ModelNewShipWeightChanged + object: model]; + + [notifyCenter addObserver : self + selector : @selector(scaleAction:) + name : ORAxisRangeChangedNotification + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(miscAttributesChanged:) + name : ORMiscAttributesChanged + object : model]; + + [notifyCenter addObserver : self + selector : @selector(updateTimePlot:) + name : ORRateAverageChangedNotification + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(printIntervalChanged:) + name : ORDefender3000NewPrintIntervalChanged + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(unitsChanged:) + name : ORDefender3000NewUnitsChanged + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(commandChanged:) + name : ORDefender3000NewCommandChanged + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(tareChanged:) + name : ORDefender3000NewTareChanged + object : nil]; + + [notifyCenter addObserver : self + selector : @selector(unitsDataChanged:) + name : ORDefender3000ModelNewUnitDataChanged + object : nil]; + +} + +- (void) updateWindow +{ + [super updateWindow]; + [self lockChanged:nil]; + [self portStateChanged:nil]; + [self portNameChanged:nil]; + [self weightChanged:nil]; + [self pollTimeChanged:nil]; + [self shipWeightChanged:nil]; + [self updateTimePlot:nil]; + [self miscAttributesChanged:nil]; + [self printIntervalChanged:nil]; + //[self unitsChanged:nil]; + [self commandChanged:nil]; + [self tareChanged:nil]; + [self unitsChanged:nil]; +} + +- (void) scaleAction:(NSNotification*)aNote +{ + if(aNote == nil || [aNote object] == [plotter0 xAxis]){ + [model setMiscAttributes:[(ORAxis*)[plotter0 xAxis]attributes] forKey:@"XAttributes0"]; + }; + + if(aNote == nil || [aNote object] == [plotter0 yAxis]){ + [model setMiscAttributes:[(ORAxis*)[plotter0 yAxis]attributes] forKey:@"YAttributes0"]; + }; +} + +- (void) miscAttributesChanged:(NSNotification*)aNote +{ + + NSString* key = [[aNote userInfo] objectForKey:ORMiscAttributeKey]; + NSMutableDictionary* attrib = [model miscAttributesForKey:key]; + + if(aNote == nil || [key isEqualToString:@"XAttributes0"]){ + if(aNote==nil)attrib = [model miscAttributesForKey:@"XAttributes0"]; + if(attrib){ + [(ORAxis*)[plotter0 xAxis] setAttributes:attrib]; + [plotter0 setNeedsDisplay:YES]; + [[plotter0 xAxis] setNeedsDisplay:YES]; + } + } + if(aNote == nil || [key isEqualToString:@"YAttributes0"]){ + if(aNote==nil)attrib = [model miscAttributesForKey:@"YAttributes0"]; + if(attrib){ + [(ORAxis*)[plotter0 yAxis] setAttributes:attrib]; + [plotter0 setNeedsDisplay:YES]; + [[plotter0 yAxis] setNeedsDisplay:YES]; + } + } +} + +- (void) updateTimePlot:(NSNotification*)aNote +{ + if(!aNote || ([aNote object] == [model timeRate])){ + [plotter0 setNeedsDisplay:YES]; + } +} + +- (void) shipWeightChanged:(NSNotification*)aNote +{ + [shipWeightButton setIntValue: [model shipWeight]]; +} + +- (void) printIntervalChanged:(NSNotification*)aNote +{ + [printIntervalField setIntValue: [model printInterval]]; +} + +- (void) tareChanged:(NSNotification*)aNote +{ + [tareField setIntValue: [model tare]]; +} + +- (void) unitsDataChanged:(NSNotification*)aNote +{ + [unitsField setStringValue:[model getUnitString]]; +} + +- (void) unitsChanged:(NSNotification*)aNote +{ + [unitsPopup selectItemWithTag: [(ORDefender3000ModelNew*)model units]]; +} + +- (void) commandChanged:(NSNotification*)aNote +{ + [commandPopup selectItemWithTag: [model command]]; +} + +- (void) weightChanged:(NSNotification*)aNote +{ + [weightField setFloatValue:[model weight]]; + uint32_t t = [model timeMeasured]; + NSDate* theDate; + if(t){ + theDate = [NSDate dateWithTimeIntervalSince1970:t]; + [timeField setObjectValue:[theDate stdDescription]]; + } + else [timeField setObjectValue:@"--"]; +} + + +- (void) checkGlobalSecurity +{ + BOOL secure = [[[NSUserDefaults standardUserDefaults] objectForKey:OROrcaSecurityEnabled] boolValue]; + [gSecurity setLock:ORDefender3000NewLock to:secure]; + [lockButton setEnabled:secure]; +} + +- (void) lockChanged:(NSNotification*)aNote +{ + BOOL runInProgress = [gOrcaGlobals runInProgress]; + BOOL lockedOrRunningMaintenance = [gSecurity runInProgressButNotType:eMaintenanceRunType orIsLocked:ORDefender3000NewLock]; + BOOL locked = [gSecurity isLocked:ORDefender3000NewLock]; + + [lockButton setState: locked]; + + [portListPopup setEnabled:!locked]; + [openPortButton setEnabled:!locked]; + + [self updateButtonStates]; + + NSString* s = @""; + if(lockedOrRunningMaintenance){ + if(runInProgress && ![gSecurity isLocked:ORDefender3000NewLock])s = @"Not in Maintenance Run."; + } + [lockDocField setStringValue:s]; + +} + +- (void) updateButtonStates +{ + BOOL locked = [gSecurity isLocked:ORDefender3000NewLock]; + bool portOpen = [[model serialPort] isOpen]; + + [unitsPopup setEnabled:!locked && portOpen]; + [commandPopup setEnabled:!locked && portOpen]; + [printIntervalField setEnabled:!locked && portOpen]; + [tareField setEnabled:!locked && portOpen]; + [shipWeightButton setEnabled:!locked && portOpen]; + [pollTimePopup setEnabled:!locked && portOpen]; + [sendCmdButton setEnabled:!locked && portOpen]; +} + +- (void) portStateChanged:(NSNotification*)aNote +{ + if(aNote == nil || [aNote object] == [model serialPort]){ + if([model serialPort]){ + [openPortButton setEnabled:YES]; + + if([[model serialPort] isOpen]){ + [openPortButton setTitle:@"Close"]; + [portStateField setTextColor:[NSColor colorWithCalibratedRed:0.0 green:.8 blue:0.0 alpha:1.0]]; + [portStateField setStringValue:@"Open"]; + } + else { + [openPortButton setTitle:@"Open"]; + [portStateField setStringValue:@"Closed"]; + [portStateField setTextColor:[NSColor redColor]]; + } + } + else { + [openPortButton setEnabled:NO]; + [portStateField setTextColor:[NSColor blackColor]]; + [portStateField setStringValue:@"---"]; + [openPortButton setTitle:@"---"]; + } + [self updateButtonStates]; + } +} + +- (void) pollTimeChanged:(NSNotification*)aNote +{ + [pollTimePopup selectItemWithTag:[model pollTime]]; +} + +- (void) portNameChanged:(NSNotification*)aNote +{ + NSString* portName = [model portName]; + + NSEnumerator *enumerator = [ORSerialPortList portEnumerator]; + ORSerialPort *aPort; + + [portListPopup selectItemAtIndex:0]; //the default + while (aPort = [enumerator nextObject]) { + if([portName isEqualToString:[aPort name]]){ + [portListPopup selectItemWithTitle:portName]; + break; + } + } + [self portStateChanged:nil]; +} + +#pragma mark ***Actions +- (IBAction) printIntervalAction:(id)sender +{ + [model setPrintInterval:[sender intValue]]; +} + +- (IBAction) tareAction:(id)sender +{ + [model setTare:[sender intValue]]; +} + +- (IBAction) sendCommandAction:(id)sender +{ + [self endEditing]; + [model sendCommand]; +} + +- (void) shipWeightAction:(id)sender +{ + [model setShipWeight:[sender intValue]]; +} + +- (IBAction) lockAction:(id) sender +{ + [gSecurity tryToSetLock:ORDefender3000NewLock to:[sender intValue] forWindow:[self window]]; +} + +- (IBAction) portListAction:(id) sender +{ + [model setPortName: [portListPopup titleOfSelectedItem]]; +} + +- (IBAction) openPortAction:(id)sender +{ + [model openPort:![[model serialPort] isOpen]]; +} + +- (IBAction) pollTimeAction:(id)sender +{ + [model setPollTime:(int)[[sender selectedItem] tag]]; +} +- (IBAction) unitsAction:(id)sender +{ + [model setUnits:(int)[[sender selectedItem] tag]]; +} + +#pragma mark •••Data Source +- (int) numberPointsInPlot:(id)aPlotter +{ + return (int)[[model timeRate] count]; +} + +- (void) plotter:(id)aPlotter index:(int)i x:(double*)xValue y:(double*)yValue +{ + int count = (int)[[model timeRate] count]; + int index = count-i-1; + *xValue = [[model timeRate] timeSampledAtIndex:index]; + *yValue = [[model timeRate] valueAtIndex:index]; +} + +@end + +@implementation ORDefender3000ControllerNew (private) + +- (void) populatePortListPopup +{ + NSEnumerator *enumerator = [ORSerialPortList portEnumerator]; + ORSerialPort *aPort; + [portListPopup removeAllItems]; + [portListPopup addItemWithTitle:@"--"]; + + while (aPort = [enumerator nextObject]) { + [portListPopup addItemWithTitle:[aPort name]]; + } +} +@end + diff --git a/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000DecodersNew.h b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000DecodersNew.h new file mode 100644 index 00000000..2674ddde --- /dev/null +++ b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000DecodersNew.h @@ -0,0 +1,31 @@ +// +// ORDefender3000Decoders.h +// Orca +// +// Created by Mark Howe on 05/14/2024. +// Copyright 2024 CENPA, University of North Carolina. All rights reserved. +//----------------------------------------------------------- +//This program was prepared for the Regents of the University of +//North Carolina sponsored in part by the United States +//Department of Energy (DOE) under Grant #DE-FG02-97ER41020. +//The University has certain rights in the program pursuant to +//the contract and the program should not be copied or distributed +//outside your organization. The DOE and the University of +//North Carolina reserve all rights in the program. Neither the authors, +//University of North Carolina, or U.S. Government make any warranty, +//express or implied, or assume any liability or responsibility +//for the use of this software. +//------------------------------------------------------------- + + +#import "ORBaseDecoder.h" + +@class ORDataPacket; +@class ORDataSet; + +@interface ORDefender3000DecoderForWeightNew : ORBaseDecoder { +} +- (NSString*) getUnitKey:(unsigned short)aUnit; +- (uint32_t) decodeData:(void*)someData fromDecoder:(ORDecoder*)aDecoder intoDataSet:(ORDataSet*)aDataSet; +- (NSString*) dataRecordDescription:(uint32_t*)dataPtr; +@end diff --git a/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000DecodersNew.m b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000DecodersNew.m new file mode 100644 index 00000000..5d1e2380 --- /dev/null +++ b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000DecodersNew.m @@ -0,0 +1,89 @@ +// +// ORDefender3000Decoders.m +// Orca +// +// Created by Mark Howe on 05/14/2024. +// Copyright 2024 CENPA, University of North Carolina. All rights reserved. +//----------------------------------------------------------- +//This program was prepared for the Regents of the University of +//North Carolina sponsored in part by the United States +//Department of Energy (DOE) under Grant #DE-FG02-97ER41020. +//The University has certain rights in the program pursuant to +//the contract and the program should not be copied or distributed +//outside your organization. The DOE and the University of +//North Carolina reserve all rights in the program. Neither the authors, +//University of North Carolina, or U.S. Government make any warranty, +//express or implied, or assume any liability or responsibility +//for the use of this software. +//------------------------------------------------------------- + +#import "ORDefender3000DecodersNew.h" +#import "ORDataPacket.h" +#import "ORDataSet.h" + +//----------------------------------------------------------------------------------- +// Data Format +//xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx +//^^^^ ^^^^ ^^^^ ^^-----------------------data id +// ^^ ^^^^ ^^^^ ^^^^ ^^^^-length in longs +// xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx +// ^^^^ ^^^^ ^^^^ ^^^^- device id +// xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx weight encoded as a float +// xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx time weight taken in seconds since Jan 1, 1970 +// xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx format data +// ^^^-- 1:g,2:kg,3:lb,4:oz,5:lb:oz +// ^^^------- 0:unknown,1:Dynamic +//------------------------------------------------------------------------------------- +static NSString* kDefender3000Unit[8] = { + //pre-make some keys for speed. + @"Unit 0",@"Unit 1",@"Unit 2",@"Unit 3",@"Unit 4",@"Unit 5",@"Unit 6",@"Unit 7" +}; + +@implementation ORDefender3000DecoderForWeightNew + +- (NSString*) getUnitKey:(unsigned short)aUnit +{ + if(aUnit<8) return kDefender3000Unit[aUnit]; + else return [NSString stringWithFormat:@"Unit %d",aUnit]; +} + +- (uint32_t) decodeData:(void*)someData fromDecoder:(ORDecoder*)aDecoder intoDataSet:(ORDataSet*)aDataSet +{ + uint32_t *dataPtr = (uint32_t*)someData; + union { + float asFloat; + uint32_t asLong; + }theTemp; + + int index = 2; + theTemp.asLong = dataPtr[index]; //encoded as float, use union to convert + [aDataSet loadTimeSeries:theTemp.asFloat + atTime:dataPtr[index+1] + sender:self + withKeys:@"Defender", + [self getUnitKey:dataPtr[1] & 0x0000ffff], + nil]; + + return ExtractLength(dataPtr[0]); +} + +- (NSString*) dataRecordDescription:(uint32_t*)dataPtr +{ + NSString* title= @"Defender Weight Record\n\n"; + NSString* theString = [NSString stringWithFormat:@"%@\n",title]; + union { + float asFloat; + uint32_t asLong; + }theData; + theString = [theString stringByAppendingFormat:@"HW ID = %u\n",dataPtr[1] & 0x0000ffff]; + int index = 2; + theData.asLong = dataPtr[index]; + + NSDate* date = [NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)dataPtr[index+1]]; + theString = [theString stringByAppendingFormat:@"%.2f %@\n",theData.asFloat,[date stdDescription]]; + + return theString; +} +@end + + diff --git a/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ModelNew.h b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ModelNew.h new file mode 100644 index 00000000..3a9149c3 --- /dev/null +++ b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ModelNew.h @@ -0,0 +1,141 @@ +//-------------------------------------------------------- +// ORDefender3000Model +// Orca +// +// Created by Mark Howe on 05/14/2024. +// Copyright 2024 CENPA, University of North Carolina. All rights reserved. +//----------------------------------------------------------- +//This program was prepared for the Regents of the University of +//North Carolina sponsored in part by the United States +//Department of Energy (DOE) under Grant #DE-FG02-97ER41020. +//The University has certain rights in the program pursuant to +//the contract and the program should not be copied or distributed +//outside your organization. The DOE and the University of +//North Carolina reserve all rights in the program. Neither the authors, +//University of North Carolina, or U.S. Government make any warranty, +//express or implied, or assume any liability or responsibility +//for the use of this software. +//------------------------------------------------------------- +#pragma mark ***Imported Files +#import "ORAdcProcessing.h" +#import "ORInFluxDBModel.h" + +@class ORSerialPort; +@class ORTimeRate; + +@interface ORDefender3000ModelNew : OrcaObject +{ + @private + NSString* portName; + ORInFluxDBModel* InFluxDB; + BOOL portWasOpen; + ORSerialPort* serialPort; + uint32_t dataId; + NSString* lastRequest; + NSMutableArray* cmdQueue; + float weight; + uint32_t timeMeasured; + int pollTime; + NSMutableString* buffer; + BOOL shipWeight; + ORTimeRate* timeRate; + uint16_t printInterval; + uint16_t tare; + uint8_t units; + uint8_t command; + uint8_t unitData; + uint8_t modeData; + + BOOL processedRunStart; + BOOL processedCloseRun; + BOOL processCheckedOnce; + float processLimitHigh; //should be set by user + float processLimitLow; + +} + +#pragma mark ***Initialization +- (id) init; +- (void) dealloc; + +- (void) registerNotificationObservers; +- (void) dataReceived:(NSNotification*)note; + +#pragma mark ***Accessors +- (ORSerialPort*) serialPort; +- (void) setSerialPort:(ORSerialPort*)aSerialPort; +- (BOOL) portWasOpen; +- (void) setPortWasOpen:(BOOL)aPortWasOpen; +- (NSString*) portName; +- (void) setPortName:(NSString*)aPortName; +- (ORTimeRate*)timeRate; +- (BOOL) shipWeight; +- (void) setShipWeight:(BOOL)aShipWeight; +- (int) pollTime; +- (void) setPollTime:(int)aPollTime; +- (NSString*) lastRequest; +- (void) setLastRequest:(NSString*)aRequest; +- (void) openPort:(BOOL)state; +- (uint32_t) timeMeasured; +- (void) setWeight:(float)aValue; +- (float) convertSerialWeightToPound:(float)aValue; +- (float) convertWeightToSelectedUnit:(float)aValue; +- (float) weight; +- (uint16_t) printInterval; +- (void) setPrintInterval:(uint16_t)aValue; +- (uint8_t) units; +- (void) setUnits:(uint8_t)aValue; +- (uint8_t) command; +- (void) setCommand:(uint8_t)aValue; +- (float) tare; +- (void) setTare:(float)aValue; +- (void) sendAllCommands; + +#pragma mark ***Data Records +- (void) appendDataDescription:(ORDataPacket*)aDataPacket userInfo:(NSDictionary*)userInfo; +- (NSDictionary*) dataRecordDescription; +- (uint32_t) dataId; +- (void) setDataId: (uint32_t) DataId; +- (void) setDataIds:(id)assigner; +- (void) syncDataIdsWith:(id)anotherDefender3000New; + +- (void) shipWeightData; +- (void) sendCommand; +- (NSString*) getUnitString; + +#pragma mark ***Commands +- (void) addCmdToQueue:(NSString*)aCmd; +- (void) readWeight; + +- (id) initWithCoder:(NSCoder*)decoder; +- (void) encodeWithCoder:(NSCoder*)encoder; + +#pragma mark •••Bit Processing Protocol +- (void) processIsStarting; +- (void) processIsStopping; +- (void) startProcessCycle; +- (void) endProcessCycle; +- (NSString*) identifier; +- (NSString*) processingTitle; +- (double) convertedValue:(int)aChan; +- (double) maxValueForChan:(int)aChan; +- (double) minValueForChan:(int)aChan; +- (void) getAlarmRangeLow:(double*)theLowLimit high:(double*)theHighLimit channel:(int)channel; +- (BOOL) processValue:(int)channel; +- (void) setProcessOutput:(int)channel value:(int)value; + +@end + +extern NSString* ORDefender3000ModelNewShipWeightChanged; +extern NSString* ORDefender3000ModelNewPollTimeChanged; +extern NSString* ORDefender3000ModelNewSerialPortChanged; +extern NSString* ORDefender3000NewLock; +extern NSString* ORDefender3000ModelNewPortNameChanged; +extern NSString* ORDefender3000ModelNewPortStateChanged; +extern NSString* ORDefender3000NewWeightArrayChanged; +extern NSString* ORDefender3000NewWeightChanged; +extern NSString* ORDefender3000NewPrintIntervalChanged; +extern NSString* ORDefender3000NewUnitsChanged; +extern NSString* ORDefender3000NewCommandChanged; +extern NSString* ORDefender3000NewTareChanged; +extern NSString* ORDefender3000ModelNewUnitDataChanged; diff --git a/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ModelNew.m b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ModelNew.m new file mode 100644 index 00000000..963ec740 --- /dev/null +++ b/Source/Objects/Hardware/Serial/Defender3000New/ORDefender3000ModelNew.m @@ -0,0 +1,802 @@ +//-------------------------------------------------------- +// ORDefender3000Model +// Orca +// +// Created by Mark Howe on 05/14/2024. +// Copyright 2024 CENPA, University of North Carolina. All rights reserved. +//----------------------------------------------------------- +//This program was prepared for the Regents of the University of +//North Carolina sponsored in part by the United States +//Department of Energy (DOE) under Grant #DE-FG02-97ER41020. +//The University has certain rights in the program pursuant to +//the contract and the program should not be copied or distributed +//outside your organization. The DOE and the University of +//North Carolina reserve all rights in the program. Neither the authors, +//University of North Carolina, or U.S. Government make any warranty, +//express or implied, or assume any liability or responsibility +//for the use of this software. +//------------------------------------------------------------- +#pragma mark ***Imported Files + +#import "ORDefender3000ModelNew.h" +#import "ORSerialPort.h" +#import "ORSerialPortList.h" +#import "ORSerialPort.h" +#import "ORSerialPortAdditions.h" +#import "ORDataTypeAssigner.h" +#import "ORDataPacket.h" +#import "ORTimeRate.h" + +#pragma mark ***External Strings +NSString* ORDefender3000ModelNewShipWeightChanged = @"ORDefender3000ModelNewShipWeightChanged"; +NSString* ORDefender3000ModelNewPollTimeChanged = @"ORDefender3000ModelNewPollTimeChanged"; +NSString* ORDefender3000ModelNewSerialPortChanged = @"ORDefender3000ModelNewSerialPortChanged"; +NSString* ORDefender3000ModelNewPortNameChanged = @"ORDefender3000ModelNewPortNameChanged"; +NSString* ORDefender3000ModelNewPortStateChanged = @"ORDefender3000ModelNewPortStateChanged"; +NSString* ORDefender3000NewWeightArrayChanged = @"ORDefender3000NewWeightArrayChanged"; +NSString* ORDefender3000NewWeightChanged = @"ORDefender3000NewWeightChanged"; +NSString* ORDefender3000NewPrintIntervalChanged = @"ORDefender3000NewPrintIntervalChanged"; +NSString* ORDefender3000NewUnitsChanged = @"ORDefender3000NewUnitsChanged"; +NSString* ORDefender3000NewCommandChanged = @"ORDefender3000NewCommandChanged"; +NSString* ORDefender3000NewTareChanged = @"ORDefender3000NewTareChanged"; +NSString* ORDefender3000ModelNewUnitDataChanged = @"ORDefender3000ModelNewUnitDataChanged"; +NSString* ORDefender3000NewLock = @"ORDefender3000NewLock"; + +@interface ORDefender3000ModelNew (private) +- (void) runStarted:(NSNotification*)aNote; +- (void) runStopped:(NSNotification*)aNote; +- (void) timeout; +- (void) processOneCommandFromQueue; +- (void) process_response:(NSString*)theResponse; +- (void) pollWeight; +- (void) setUnitData:(NSString*)theUnit; +- (void) setModeData:(NSString*)theMode; + +@end + +@implementation ORDefender3000ModelNew +- (id) init +{ + self = [super init]; + [self registerNotificationObservers]; + return self; +} + +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + [buffer release]; + [cmdQueue release]; + [lastRequest release]; + [portName release]; + if([serialPort isOpen]){ + [serialPort close]; + } + [serialPort release]; + [timeRate release]; + + + [super dealloc]; +} + +- (void) setUpImage +{ + [self setImage:[NSImage imageNamed:@"Defender3000New.tif"]]; +} + +- (void) makeMainController +{ + [self linkToController:@"ORDefender3000ControllerNew"]; +} + +- (void) registerNotificationObservers +{ + NSNotificationCenter* notifyCenter = [NSNotificationCenter defaultCenter]; + + [notifyCenter addObserver : self + selector : @selector(dataReceived:) + name : ORSerialPortDataReceived + object : nil]; + + [notifyCenter addObserver: self + selector: @selector(runStarted:) + name: ORRunStartedNotification + object: nil]; + + [notifyCenter addObserver: self + selector: @selector(runStopped:) + name: ORRunStoppedNotification + object: nil]; + +} + +- (void) dataReceived:(NSNotification*)note +{ + if([[note userInfo] objectForKey:@"serialPort"] == serialPort){ + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeout) object:nil]; + NSString* theString = [[[[NSString alloc] initWithData:[[note userInfo] objectForKey:@"data"] + encoding:NSASCIIStringEncoding] autorelease] uppercaseString]; + + //the serial port may break the data up into small chunks, so we have to accumulate the chunks until + //we get a full piece. + theString = [[theString componentsSeparatedByString:@"\n"] componentsJoinedByString:@""]; + if(!buffer)buffer = [[NSMutableString string] retain]; + [buffer appendString:theString]; + + do { + NSRange lineRange = [buffer rangeOfString:@"\r"]; + if(lineRange.location!= NSNotFound){ + NSMutableString* theResponse = [[[buffer substringToIndex:lineRange.location+1] mutableCopy] autorelease]; + [buffer deleteCharactersInRange:NSMakeRange(0,lineRange.location+1)]; //take the cmd out of the buffer + + [self process_response:theResponse]; + + [self setLastRequest:nil]; //clear the last request + [self processOneCommandFromQueue]; //do the next command in the queue + } + } while([buffer rangeOfString:@"\r"].location!= NSNotFound); + } +} + +- (void) shipWeightData +{ + //----------------------------------------------------------------------------------- + // Data Format + //xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx + //^^^^ ^^^^ ^^^^ ^^-----------------------data id + // ^^ ^^^^ ^^^^ ^^^^ ^^^^-length in longs + // xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx + // ^^^^ ^^^^ ^^^^ ^^^^- device id + // xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx weight encoded as a float + // xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx time weight taken in seconds since Jan 1, 1970 + // xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx format data + // ^^^-- 1:g,2:kg,3:lb,4:oz,5:lb:oz + // ^^^------- 0:unknown,1:Dynamic + //------------------------------------------------------------------------------------- + if([[ORGlobal sharedGlobal] runInProgress]){ + + uint32_t data[5]; + data[0] = dataId | 5; + data[1] = ([self uniqueIdNumber]&0x0000fffff); + + union { + float asFloat; + uint32_t asLong; + }theData; + + theData.asFloat = weight; + data[2] = theData.asLong; + data[3] = timeMeasured; + + data[4] = (unitData & 0x7) << 0 | //1:g,2:kg,3:lb,4:oz,5:lb:oz + (modeData & 0x7) << 4 ; //0:Unknown,1:Dynamic + + [[NSNotificationCenter defaultCenter] postNotificationName:ORQueueRecordForShippingNotification + object:[NSData dataWithBytes:data length:sizeof(int32_t)*4]]; + } +} + + +#pragma mark ***Accessors +- (ORTimeRate*)timeRate +{ + return timeRate; +} + +- (BOOL) shipWeight +{ + return shipWeight; +} + +- (void) setShipWeight:(BOOL)aShipWeight +{ + [[[self undoManager] prepareWithInvocationTarget:self] setShipWeight:shipWeight]; + + shipWeight = aShipWeight; + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000ModelNewShipWeightChanged object:self]; +} + +- (int) pollTime +{ + return pollTime; +} + +- (void) setPollTime:(int)aPollTime +{ + [[[self undoManager] prepareWithInvocationTarget:self] setPollTime:pollTime]; + pollTime = aPollTime; + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000ModelNewPollTimeChanged object:self]; + + if(pollTime){ + [self performSelector:@selector(pollWeight) withObject:nil afterDelay:2]; + } + else { + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(pollWeight) object:nil]; + } +} + +- (float) weight +{ + return weight; +} + +- (uint32_t) timeMeasured +{ + return timeMeasured; +} + +- (void) setWeight:(float)aValue; +{ + weight = [self convertWeightToSelectedUnit : [self convertSerialWeightToPound: aValue]]; + //weight = aValue; + //get the time(UT!) + time_t ut_Time; + time(&ut_Time); + //struct tm* theTimeGMTAsStruct = gmtime(&theTime); + timeMeasured = (uint32_t)ut_Time; + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000NewWeightChanged + object:self]; + + if(timeRate == nil) timeRate = [[ORTimeRate alloc] init]; + [timeRate addDataToTimeAverage:aValue]; +} +- (float) convertSerialWeightToPound:(float)aValue; +{ + switch (unitData) { + case 1: // Grams to Pounds + weight = aValue * 0.00220462; + break; + + case 2: // Kilograms to Pounds + weight = aValue * 2.20462; + break; + + case 3: // Pounds + weight = aValue; + // Already in pounds + break; + + case 4: // Ounces to Pounds + weight = aValue / 16.0; + break; + + case 5: // lb:oz to Pounds + /* Logic: Assumes 'weight' is total ounces. + If weight is 18 (representing 1lb 2oz), 18 / 16 = 1.125 lbs + */ + weight = aValue / 16.0; + break; + + default: + break; + } + return weight; +} + +- (float) convertWeightToSelectedUnit:(float)aValue; +{ + switch (units) { + case 1: // pounds to gm + weight = aValue / 0.00220462; + break; + + case 2: // pounds to Kilograms + weight = aValue / 2.20462; + break; + + case 3: // Pounds + weight = aValue; + // Already in pounds + break; + + case 4: // Pounds to Ounces + weight = aValue * 16.0; + break; + + case 5: // Pounds to lb:oz + /* Logic: Assumes 'weight' is total ounces. + If weight is 18 (representing 1lb 2oz), 18 / 16 = 1.125 lbs + */ + weight = aValue * 16.0; + break; + + default: + break; + } + return weight; +} + + +- (uint8_t) command +{ + return command; +} + +- (void) setCommand:(uint8_t)aValue +{ + [[[self undoManager] prepareWithInvocationTarget:self] setCommand:command]; + + if(command>11)command=11; + + command = aValue; + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000NewCommandChanged + object:self]; +} + +- (uint16_t) printInterval +{ + return printInterval; +} + +- (void) setPrintInterval:(uint16_t)aValue +{ + [[[self undoManager] prepareWithInvocationTarget:self] setPrintInterval:printInterval]; + + if(aValue>3600)aValue = 3600; + + printInterval = aValue; + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000NewPrintIntervalChanged + object:self]; +} + +- (uint8_t) units +{ + return units; +} + +- (void) setUnits:(uint8_t)aValue +{ + [[[self undoManager] prepareWithInvocationTarget:self] setUnits:units]; + + if(units<1) units = 1; + else if(units>5)units = 5; + + units = aValue; + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000NewUnitsChanged + object:self]; +} +- (float) tare +{ + return tare; +} + +- (void) setTare:(float)aValue +{ + [[[self undoManager] prepareWithInvocationTarget:self] setTare:tare]; + + tare = aValue; + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000NewTareChanged + object:self]; +} +- (NSString*) lastRequest +{ + return lastRequest; +} + +- (void) setLastRequest:(NSString*)aRequest +{ + [lastRequest autorelease]; + lastRequest = [aRequest copy]; +} + +- (BOOL) portWasOpen +{ + return portWasOpen; +} + +- (void) setPortWasOpen:(BOOL)aPortWasOpen +{ + portWasOpen = aPortWasOpen; +} + +- (NSString*) portName +{ + return portName; +} + +- (void) setPortName:(NSString*)aPortName +{ + [[[self undoManager] prepareWithInvocationTarget:self] setPortName:portName]; + + if(![aPortName isEqualToString:portName]){ + [portName autorelease]; + portName = [aPortName copy]; + + BOOL valid = NO; + NSEnumerator *enumerator = [ORSerialPortList portEnumerator]; + ORSerialPort *aPort; + while (aPort = [enumerator nextObject]) { + if([portName isEqualToString:[aPort name]]){ + [self setSerialPort:aPort]; + if(portWasOpen){ + [self openPort:YES]; + } + valid = YES; + break; + } + } + if(!valid){ + [self setSerialPort:nil]; + } + } + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000ModelNewPortNameChanged object:self]; +} + +- (ORSerialPort*) serialPort +{ + return serialPort; +} + +- (void) setSerialPort:(ORSerialPort*)aSerialPort +{ + [aSerialPort retain]; + [serialPort release]; + serialPort = aSerialPort; + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000ModelNewSerialPortChanged object:self]; +} + +- (void) openPort:(BOOL)state +{ + if(state) { + [serialPort open]; + [serialPort setSpeed:9600]; + [serialPort setParityNone]; + [serialPort setStopBits2:1]; + [serialPort setDataBits:8]; + [serialPort commitChanges]; + } + else [serialPort close]; + portWasOpen = [serialPort isOpen]; + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000ModelNewPortStateChanged object:self]; + +} + + +#pragma mark ***Archival +- (id) initWithCoder:(NSCoder*)decoder +{ + self = [super initWithCoder:decoder]; + [[self undoManager] disableUndoRegistration]; + [self setShipWeight: [decoder decodeBoolForKey: @"shipWeight"]]; + [self setPollTime: [decoder decodeIntForKey: @"pollTime"]]; + [self setPortWasOpen:[decoder decodeBoolForKey: @"portWasOpen"]]; + [self setPortName: [decoder decodeObjectForKey:@"portName"]]; + [self setUnits: [decoder decodeIntForKey: @"units"]]; + [self setTare: [decoder decodeIntForKey: @"tare"]]; + [self setCommand: [decoder decodeIntForKey: @"command"]]; + [self setPrintInterval: [decoder decodeIntForKey: @"printInterval"]]; + [[self undoManager] enableUndoRegistration]; + timeRate = [[ORTimeRate alloc] init]; + + [self registerNotificationObservers]; + + return self; +} + +- (void) encodeWithCoder:(NSCoder*)encoder +{ + [super encodeWithCoder:encoder]; + [encoder encodeBool:shipWeight forKey:@"shipWeight"]; + [encoder encodeInteger:pollTime forKey:@"pollTime"]; + [encoder encodeBool:portWasOpen forKey:@"portWasOpen"]; + [encoder encodeObject:portName forKey:@"portName"]; + [encoder encodeInteger:units forKey:@"units"]; + [encoder encodeInteger:command forKey:@"command"]; + [encoder encodeInteger:tare forKey:@"tare"]; + [encoder encodeInteger:printInterval forKey:@"printInterval"]; +} + +#pragma mark *** Commands +- (void) addCmdToQueue:(NSString*)aCmd +{ + if([serialPort isOpen]){ + if(!cmdQueue)cmdQueue = [[NSMutableArray array] retain]; + [cmdQueue addObject:aCmd]; + if(!lastRequest){ + [self processOneCommandFromQueue]; + } + } +} + +- (void) readWeight +{ + [self addCmdToQueue:@"P"]; + [self addCmdToQueue:@"++ShipRecords"]; +} + +#pragma mark ***Data Records +- (uint32_t) dataId { return dataId; } +- (void) setDataId: (uint32_t) DataId +{ + dataId = DataId; +} +- (void) setDataIds:(id)assigner +{ + dataId = [assigner assignDataIds:kLongForm]; +} + +- (void) syncDataIdsWith:(id)anotherDefender3000New +{ + [self setDataId:[anotherDefender3000New dataId]]; +} + +- (void) appendDataDescription:(ORDataPacket*)aDataPacket userInfo:(NSDictionary*)userInfo +{ + //---------------------------------------------------------------------------------------- + // first add our description to the data description + [aDataPacket addDataDescriptionItem:[self dataRecordDescription] forKey:@"Defender3000ModelNew"]; +} + +- (NSDictionary*) dataRecordDescription +{ + NSMutableDictionary* dataDictionary = [NSMutableDictionary dictionary]; + NSDictionary* aDictionary = [NSDictionary dictionaryWithObjectsAndKeys: + @"ORDefender3000DecoderForWeightNew",@"decoder", + [NSNumber numberWithLong:dataId], @"dataId", + [NSNumber numberWithBool:NO], @"variable", + [NSNumber numberWithLong:4], @"length", + nil]; + [dataDictionary setObject:aDictionary forKey:@"Weights"]; + + return dataDictionary; +} + +- (void) sendAllCommands +{ + [self addCmdToQueue:[NSString stringWithFormat:@"%dP",printInterval]]; + [self addCmdToQueue:[NSString stringWithFormat:@"%dT",tare]]; + [self addCmdToQueue:[NSString stringWithFormat:@"%dU",units]]; +} + +- (void) sendCommand +{ + [self addCmdToQueue:@"P"]; + /* + //format the command + switch(command){ + case 0: [self addCmdToQueue:@"P"]; break; + case 1: + [self addCmdToQueue:[NSString stringWithFormat:@"%dP",printInterval]]; + //[self addCmdToQueue:@"P"]; + break; + case 2: [self addCmdToQueue:@"Z"]; break; + case 3: + [self addCmdToQueue:[NSString stringWithFormat:@"%dT",tare]]; + break; + case 4: [self addCmdToQueue:@"T"]; break; + case 5: [self addCmdToQueue:@"PU"]; break; + case 6: + [self addCmdToQueue:[NSString stringWithFormat:@"%dU",units]]; + break; + case 7: [self addCmdToQueue:@"PV"]; break; + case 8: + [self addCmdToQueue:[NSString stringWithFormat:@"%cR",0x1B]]; + break; + } + */ +} +- (NSString*) getUnitString +{ + switch(unitData){ + case 1: return @"g"; + case 2: return @"kg"; + case 3: return @"lb"; + case 4: return @"oz"; + case 5: return @"lb:oz"; + default:return @"kg"; + } +} +#pragma mark •••Adc Processing Protocol +- (void) processIsStarting +{ + processCheckedOnce = NO; +} + +- (void) processIsStopping +{ +} + +//note that everything called by these routines MUST be threadsafe +- (void) startProcessCycle +{ + if(!processCheckedOnce){ + @try { + [self readWeight]; + processCheckedOnce = YES; + } + @catch(NSException* localException) { + //catch this here to prevent it from falling thru, but nothing to do. + } + } +} + +- (void) endProcessCycle +{ +} + +- (NSString*) identifier +{ + return [NSString stringWithFormat:@"Defender3000New,%u",[self uniqueIdNumber]]; +} + +- (NSString*) processingTitle +{ + return [self identifier]; +} + +- (double) convertedValue:(int)aChan +{ + return weight; //chan has no meaning for this object +} + +- (double) maxValueForChan:(int)aChan +{ + return 1000; //change to max scale reading +} + +- (double) minValueForChan:(int)aChan +{ + return 0; +} + +- (BOOL) processValue:(int)channel +{ + //channel has no meaning for this object + return weight; +} + +- (void) setProcessOutput:(int)channel value:(int)value +{ + +} + +- (void)getAlarmRangeLow:(double *)theLowLimit high:(double *)theHighLimit channel:(int)channel +{ + //these values need to come from the dialog and be set by user. + *theLowLimit = -10; + *theHighLimit = 1000; +} + + +@end + +@implementation ORDefender3000ModelNew (private) +- (void) runStarted:(NSNotification*)aNote +{ +} + +- (void) runStopped:(NSNotification*)aNote +{ +} + +- (void) timeout +{ + NSLogError(@"command timeout",@"Defender 3000 New",nil); + [self setLastRequest:nil]; + [self processOneCommandFromQueue]; //do the next command in the queue +} + +- (void) processOneCommandFromQueue +{ + if([cmdQueue count] == 0) return; + NSString* aCmd = [[[cmdQueue objectAtIndex:0] retain] autorelease]; + [cmdQueue removeObjectAtIndex:0]; + if([aCmd isEqualToString:@"++ShipRecords"]){ + if(shipWeight) [self shipWeightData]; + } + else if([aCmd isEqualToString:@"++Delay"]){ + [ORTimer delay:1]; + } + else { + [self setLastRequest:aCmd]; + [self performSelector:@selector(timeout) withObject:nil afterDelay:3]; + aCmd = [aCmd stringByAppendingString:@"\r\n"]; + + [serialPort writeString:aCmd]; + if(!lastRequest){ + [self performSelector:@selector(processOneCommandFromQueue) withObject:nil afterDelay:.01]; + } + } +} + +- (void) process_response:(NSString*)theResponse +{ + //NSLog(@"%@",theResponse); + if([lastRequest isEqualToString:@"PV"]){ + } + else if([theResponse hasPrefix:@"OK"]){ + } + else if([theResponse hasPrefix:@"ES"]){ + } + else { + theResponse = [theResponse stringByReplacingOccurrencesOfString:@":" withString:@" "]; + theResponse = [theResponse removeExtraSpaces]; + theResponse = [theResponse uppercaseString]; + NSArray* components; + components = [theResponse componentsSeparatedByString:@" "]; + if([components count]>=3){ + //format is wt unit mode + [self setWeight:[[components objectAtIndex:0]floatValue]]; + [self sendDefender3000ToInflux:[[components objectAtIndex:0]doubleValue]]; + [self setUnitData: [components objectAtIndex:1]]; + [self setModeData:[components objectAtIndex:2]]; + } + else if([components count]==2){ + [self setWeight:[[components objectAtIndex:0]floatValue]]; + [self sendDefender3000ToInflux:[[components objectAtIndex:0]doubleValue]]; + [self setUnitData: [components objectAtIndex:1]]; + + if([[components objectAtIndex:0] isEqualToString:@"UNIT"]){ + [self setUnitData: [components objectAtIndex:1]]; + } + else if([[components objectAtIndex:0] isEqualToString:@"MODE"]){ + [self setModeData: [components objectAtIndex:1]]; + } + } + } +} + +-(void)sendDefender3000ToInflux:(double)weight +{ + @autoreleasepool { + // Retrieve the InFluxDB model instance + InFluxDB = [[[(ORAppDelegate*)[NSApp delegate] document] findObjectWithFullID:@"ORInFluxDBModel,1"] retain]; + if (InFluxDB == nil) { + NSLog(@"Error: Unable to find the InfluxDB model."); + return; + } + // Current timestamp + double currentTimeStamp = [[NSDate date] timeIntervalSince1970]; //timestamp is already there check. + // Create a new measurement object for the InfluxDB bucket + ORInFluxDBMeasurement *measurement = [ORInFluxDBMeasurement measurementForBucket:@"ENAP_SC_UNC" org:[InFluxDB org]]; + + [measurement start:@"Defender3000New_1"]; + [measurement addTag:@"GasOfWeight" withString:@"weightMeasured"]; + [measurement addField:@"weight" withDouble:weight]; + // Set the timestamp + [measurement setTimeStamp:currentTimeStamp]; + // Execute the database command + [InFluxDB executeDBCmd:measurement]; + // Manually release InFluxDB if using manual memory management (MRC) + [InFluxDB release]; + } +} + + + + +- (void) pollWeight +{ + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(pollWeight) object:nil]; + [self readWeight]; + [self performSelector:@selector(pollWeight) withObject:nil afterDelay:pollTime]; +} + +- (void) setUnitData:(NSString*)theUnit +{ + theUnit = 0; + if([theUnit isEqualToString: @"G"]) unitData = 1; + else if([theUnit isEqualToString:@"KG"]) unitData = 2; + else if([theUnit isEqualToString:@"LB"]) unitData = 3; + else if([theUnit isEqualToString:@"OZ"]) unitData = 4; + else if([theUnit isEqualToString:@"LB:OZ"]) unitData = 5; + else theUnit = 0; + + [[NSNotificationCenter defaultCenter] postNotificationName:ORDefender3000ModelNewUnitDataChanged object:self]; +} + +- (void) setModeData:(NSString*)theMode +{ + if([theMode isEqualToString: @"DYNAMIC"]) modeData = 1; + else modeData = 0; +} + +@end