diff --git a/src/app/group-monitor/backend.service.ts b/src/app/group-monitor/backend.service.ts
index 8d240b760c7c77b392c3342012a5c87b6f0a9dc5..f9b6d84f511acb070de789f82559817bc026191a 100644
--- a/src/app/group-monitor/backend.service.ts
+++ b/src/app/group-monitor/backend.service.ts
@@ -75,4 +75,19 @@ export class BackendService extends WebsocketBackendService<TestSession[]> {
       )
       .subscribe();
   }
+
+    unlock(group_name: string, testIds: number[]): Subscription {
+
+        return this.http
+            .post(this.serverUrl +  `monitor/group/${group_name}/tests/unlock`, {testIds})
+            .pipe(
+                catchError(() => {
+                    // TODO interceptor should have interfered and moved to error-page ...
+                    // https://github.com/iqb-berlin/testcenter-frontend/issues/53
+                    console.warn(`unlocking failed: command`, testIds);
+                    return of(false);
+                })
+            )
+            .subscribe();
+    }
 }
diff --git a/src/app/group-monitor/group-monitor.component.css b/src/app/group-monitor/group-monitor.component.css
index a12ba8ca97ca24d1f84be072178268db53a96722..97e8d9d93992d6ff342194b1fc084b8fabb86b89 100644
--- a/src/app/group-monitor/group-monitor.component.css
+++ b/src/app/group-monitor/group-monitor.component.css
@@ -51,7 +51,7 @@
 }
 
 .connection-status.error {
-    background: red
+    background: #821123
 }
 
 .connection-status.ws-offline {
@@ -164,10 +164,10 @@ mat-sidenav {
 }
 
 .hide-scroll-hint .scroll-hint {
-    animation: fade 0.3s reverse forwards;
+    animation: fade-and-shrink 0.3s reverse forwards;
 }
 
-@keyframes fade {
+@keyframes fade-and-shrink {
     0% {
         opacity: 0;
         transform: scale(0)
@@ -200,11 +200,32 @@ mat-sidenav {
     text-transform: uppercase;
 }
 
+.alert-warning {
+    border-radius: 4px;
+    box-sizing: border-box;
+    margin: 0 0 0.5em 0;
+    width: 100%;
+    padding: 14px 16px;
+    min-height: 48px;
+    color: hsla(0,0%,100%,.7);
+    background: #821123;
+    display: inline-flex;
+    vertical-align: middle;
+    align-items: center;
+    animation: fade 30s reverse forwards;
+}
 
+.alert-warning mat-icon {
+    margin-right: 4px;
+}
 
+@keyframes fade {
+    0% {
+        opacity: 0;
+    }
 
-
-
-
-
+    100% {
+        opacity: 1;
+    }
+}
 
diff --git a/src/app/group-monitor/group-monitor.component.html b/src/app/group-monitor/group-monitor.component.html
index 35dbb5f22c086a25b1bd03da26a638a4833ac071..3f4645ac8add0557513ed5a8a1a57fea6ed124d9 100644
--- a/src/app/group-monitor/group-monitor.component.html
+++ b/src/app/group-monitor/group-monitor.component.html
@@ -99,6 +99,12 @@
                 </button>
             </div>
 
+            <div class="toolbar-section">
+                <button mat-raised-button class="control" color="primary" (click)="testCommandUnlock()" [disabled]="!isUnlockAllowed()">
+                    <mat-icon>lock-open</mat-icon>ENTSPERREN
+                </button>
+            </div>
+
             <hr>
 
             <div class="toolbar-section">
@@ -108,6 +114,12 @@
                     <mat-radio-button value="unit" disabled>Aufgabe</mat-radio-button>
                 </mat-radio-group>
             </div>
+
+            <div class="toolbar-section">
+                <div *ngFor="let warning of warnings | keyvalue" class="alert-warning">
+                    <mat-icon>warning</mat-icon>{{warning.value.text}}
+                </div>
+            </div>
         </mat-sidenav>
 
         <mat-sidenav-content>
@@ -172,10 +184,7 @@
                     </table>
                 </div>
             </div>
-
         </mat-sidenav-content>
-
-
     </mat-sidenav-container>
 
     <button
diff --git a/src/app/group-monitor/group-monitor.component.ts b/src/app/group-monitor/group-monitor.component.ts
index 67178830f529be5e10d646fb142a5660a6456c29..4ec4f716722fe88bd793e4e7d5525ee9c0370e03 100644
--- a/src/app/group-monitor/group-monitor.component.ts
+++ b/src/app/group-monitor/group-monitor.component.ts
@@ -31,6 +31,7 @@ export class GroupMonitorComponent implements OnInit, OnDestroy {
   ) {}
 
   ownGroup$: Observable<GroupData>;
+  private ownGroupName: string = '';
 
   monitor$: Observable<TestSession[]>;
   connectionStatus$: Observable<ConnectionStatus>;
@@ -80,12 +81,14 @@ export class GroupMonitorComponent implements OnInit, OnDestroy {
   sessionCheckedGroupCount: number;
 
   isScrollable = false;
-  @ViewChild('adminbackground') mainElem:ElementRef;
 
-  private routingSubscription: Subscription = null;
+  warnings: {[key: string]: {text: string, timeout: number}} = {};
 
+  @ViewChild('adminbackground') mainElem:ElementRef;
   @ViewChild('sidenav', {static: true}) sidenav: MatSidenav;
 
+  private routingSubscription: Subscription = null;
+
   static getFirstUnit(testletOrUnit: Testlet|Unit): Unit|null {
     while (!isUnit(testletOrUnit)) {
       if (!testletOrUnit.children.length) {
@@ -107,6 +110,7 @@ export class GroupMonitorComponent implements OnInit, OnDestroy {
   ngOnInit(): void {
     this.routingSubscription = this.route.params.subscribe(params => {
       this.ownGroup$ = this.bs.getGroupData(params['group-name']);
+      this.ownGroupName = params['group-name'];
     });
 
     this.sortBy$ = new BehaviorSubject<Sort>({direction: 'asc', active: 'personLabel'});
@@ -118,8 +122,8 @@ export class GroupMonitorComponent implements OnInit, OnDestroy {
 
     combineLatest<[Sort, TestSessionFilter[], TestSession[]]>([this.sortBy$, this.filters$, this.monitor$])
       .pipe(
-          map(([sortBy, filters, sessions]) => this.sortSessions(sortBy, this.filterSessions(sessions, filters))),
-          tap(sessions => this.updateChecked(sessions))
+        map(([sortBy, filters, sessions]) => this.sortSessions(sortBy, this.filterSessions(sessions, filters))),
+        tap(sessions => this.updateChecked(sessions)),
       )
       .subscribe(this.sessions$);
 
@@ -230,16 +234,40 @@ export class GroupMonitorComponent implements OnInit, OnDestroy {
     this.bs.command('pause', [], testIds);
   }
 
-  testCommandGoto() {
+  testCommandGoto(): void {
     if ((this.sessionCheckedGroupCount === 1) && (Object.keys(this.checkedSessions).length > 0)) {
       const testIds = Object.values(this.checkedSessions)
-        .filter((session) => session.testId && session.testId > -1)
-        .map((session) => session.testId);
+        .filter(session => session.testId && session.testId > -1)
+        .map(session => session.testId);
       this.bs.command('goto', ['id', GroupMonitorComponent.getFirstUnit(this.selectedElement.element).id], testIds);
     }
   }
 
-  selectElement(selected: Selected) {
+  testCommandUnlock(): void {
+    const sessions = Object.values(this.checkedSessions)
+      .filter(session => GroupMonitorComponent.hasState(session.testState, 'status', 'locked'))
+    this.bs.unlock(this.ownGroupName, sessions.map(session => session.testId)).add(() => {
+      const plural = sessions.length > 1;
+      this.addWarning('reload-some-clients',
+          `${plural ? sessions.length : 'Ein'} Test${plural ? 's': ''} 
+          wurde${plural ? 'n': ''} entsperrt. ${plural ? 'Die': 'Der'} Teilnehmer 
+          ${plural ? 'müssen': 'muss'} die Webseite aufrufen bzw. neuladen, 
+          damit ${plural ? 'die': 'der'} Test${plural ? 's': ''} wieder aufgenommen werden kann!`
+      );
+    });
+  }
+
+  private addWarning(key, text): void {
+    if (typeof this.warnings[key] !== "undefined") {
+      window.clearTimeout(this.warnings[key].timeout);
+    }
+    this.warnings[key] = {
+      text,
+      timeout: window.setTimeout(() => delete this.warnings[key], 30000)
+    }
+  }
+
+  selectElement(selected: Selected): void {
     this.selectedElement = selected;
     let toCheck: TestSession[] = [];
     if (selected.element) {
@@ -332,30 +360,42 @@ export class GroupMonitorComponent implements OnInit, OnDestroy {
     const activeSessions = Object.values(this.checkedSessions).length && Object.values(this.checkedSessions)
       .filter((session) => GroupMonitorComponent.hasState(session.testState, 'status', 'running'));
     return activeSessions.length && activeSessions
-        .filter(session => GroupMonitorComponent.hasState(session.testState, 'status', 'running'))
-        .filter(session => GroupMonitorComponent.hasState(session.testState, 'CONTROLLER', 'PAUSED'))
-        .length === 0;
+      .filter(session => GroupMonitorComponent.hasState(session.testState, 'status', 'running'))
+      .filter(session => GroupMonitorComponent.hasState(session.testState, 'CONTROLLER', 'PAUSED'))
+      .length === 0;
   }
 
-  isResumeAllowed() {
+  isResumeAllowed(): boolean {
     const activeSessions = Object.values(this.checkedSessions)
-      .filter((session) => GroupMonitorComponent.hasState(session.testState, 'status', 'running'));
+        .filter((session) => GroupMonitorComponent.hasState(session.testState, 'status', 'running'));
     return activeSessions.length && activeSessions
-      .filter((session) => !GroupMonitorComponent.hasState(session.testState, 'CONTROLLER', 'PAUSED'))
-      .length === 0;
+        .filter((session) => !GroupMonitorComponent.hasState(session.testState, 'CONTROLLER', 'PAUSED'))
+        .length === 0;
+  }
+
+  isUnlockAllowed(): boolean {
+    const lockedSessions = Object.values(this.checkedSessions)
+        .filter(session => GroupMonitorComponent.hasState(session.testState, 'status', 'locked'));
+    return lockedSessions.length && (lockedSessions.length === Object.values(this.checkedSessions).length);
   }
 
-  ngAfterViewChecked() {
+  ngAfterViewChecked(): void {
     this.isScrollable = this.mainElem.nativeElement.clientHeight < this.mainElem.nativeElement.scrollHeight;
   }
 
-  scrollDown() {
+  scrollDown(): void {
     this.mainElem.nativeElement.scrollTo(0, this.mainElem.nativeElement.scrollHeight);
   }
 
-  updateScrollHint() {
+  updateScrollHint(): void {
     const elem = this.mainElem.nativeElement;
     const reachedBottom = (elem.scrollTop + elem.clientHeight === elem.scrollHeight);
     elem.classList[reachedBottom ? 'add' : 'remove']('hide-scroll-hint');
   }
+
+  showClientsMustBeReloadedWarning(): boolean {
+    return true;
+    // return this.sessionsMustBeReloaded && this.sessions$.getValue()
+    //     .filter(session => this.sessionsMustBeReloaded.indexOf(session.testId)) // STAND sessiosn filtern
+  }
 }
diff --git a/src/app/group-monitor/test-view/test-view.component.css b/src/app/group-monitor/test-view/test-view.component.css
index 0c1b2be9a239e445b62360e4afcf5d01a5438579..40f8a728d65b9febec130aa588482104db2afc6c 100644
--- a/src/app/group-monitor/test-view/test-view.component.css
+++ b/src/app/group-monitor/test-view/test-view.component.css
@@ -24,10 +24,6 @@ mat-icon + h1 {
     transform-style: preserve-3d;
 }
 
-.error .units {
-    background: rgba(255, 0, 0, 0.3);
-}
-
 .units:before {
     background: #003333;
     /*width: 100%;*/
@@ -156,12 +152,12 @@ mat-icon + h1 {
 }
 
 .warning {
-    color: red;
+    color: #821123;
     font-weight: bold
 }
 
 .unit-badge.danger {
-    color: red;
+    color: #821123;
 }
 .unit-badge.success {
     color: #b2ff59
diff --git a/src/app/group-monitor/test-view/test-view.component.ts b/src/app/group-monitor/test-view/test-view.component.ts
index 2729debd64c455dc26891793dc75c952779bce69..76cb76c0bfbdddab5624bc44c9ab1279e625bb36 100644
--- a/src/app/group-monitor/test-view/test-view.component.ts
+++ b/src/app/group-monitor/test-view/test-view.component.ts
@@ -112,9 +112,13 @@ export class TestViewComponent implements OnInit, OnChanges, OnDestroy {
     if (this.hasState(state, 'status', 'locked')) {
       return {tooltip: 'Test gesperrt', icon: 'lock_closed'}
     }
-    if (this.hasState(state, 'CONTROLLER', 'error')) {
+    if (this.hasState(state, 'CONTROLLER', 'ERROR')) {
       return {tooltip: 'Es ist ein Fehler aufgetreten!', icon: 'error', class: 'danger'}
     }
+    if (this.hasState(state, 'CONTROLLER', 'TERMINATED')) {
+      return {tooltip: 'Testausführung wurde beendet und kann wieder aufgenommen werden. ' +
+            'Der Browser des Teilnehmers muss ggf. neu geladen werden!', icon: 'warning', class: 'danger'}
+    }
     if (this.hasState(state, 'CONNECTION', 'LOST')) {
       return {tooltip: 'Seite wurde verlassen oder Browserfenster geschlossen!', icon: 'error', class: 'danger'}
     }